通过写入2D数组来分割错误

我的程序中有一个小的内存访问问题,我没有找到错误,也许有人可以帮助我。

我创建了一个新类型来存储rgb颜色值。 那种类型看起来像:

typedef struct pixel { unsigned char r; unsigned char g; unsigned char b; } pixel; 

在我的主程序中,我用calloc创建了一个2D动态数组,用于存储红色信息。

 pixel **pixelvalue = (pixel **) calloc(imginformation.width, sizeof(pixel)); for (i = 0; i < imginformation.width; i++) { pixelvalue[i] = (pixel *) calloc(imginformation.height, sizeof(pixel)); } 

之后我调用我的函数,它读取颜色值,谁应该将它们安全地保存到数组中。 该函数作为参数获取数组。

 ReadFile(file, imginformation (Stuff like height and so one), pixelvalue (The calloc array)); 

在该函数中,我尝试用值编写值

 pixelvalue[i][j].r = (unsigned char)fgetc(in); 

在这里我得到内存访问错误,我错了什么?

编辑

嗨,首先抱歉遗失的语言,我昨天有点累了:)。

为了理解,我创建了一个像素数组,并且元素指向另一个像素数组? 像[Point to another 1D array pixel]

用像素**pixelvalue = calloc(imginformation.width, sizeof(pixel *)); 我从类型像素创建imginformation.width指针数,每个指针显示像素,对吧?

如果你能解释一下,如果我错了,那就太棒了。 我真的很想了解它。

@ carl-norum你的意思是:

“你不应该强制转换calloc()的返回值。这样做可以隐藏#include的错误,可以回来咬你的路”。

? 我使用alloc空间作为函数的参数,而不是返回值。

谢谢你的帮助!

格尔茨

你实际上并不是在创建一个2D数组,而是在创建一个指向像素数组的指针数组。 这意味着你的第一个calloc调用应该为指针分配足够的空间,而不是像素:

 pixel **pixelvalue = calloc(imginformation.width, sizeof(pixel *)); 

您没有用语言标记您的问题,但假设它是C(基于您的typedef ,这在C ++中是不必要的),您不应该转换calloc()的返回值。 这样做可以隐藏#include错误,可以回来咬你的路。

编辑:

你问了几个后续问题。 我想,第一个答案已经得到了很好的回答,但我会试着总结一下。 你进行分配的方式,首先要分配一个指针数组 – 每个指针都指向数组的一行。 然后需要分配行本身 – 每个pixel对象的空间到达那里,并且指向行的指针存储在第一个指针数组中。

你的第二个问题,来自calloc()的返回值非常简单。 如果转换返回值,则可以隐藏自己的隐式声明错误。 由于calloc的返回类型为void * ,如果你执行以下操作:

 my_ptr = calloc(1, 2); 

一切都很好。 现在假设您没有包含stdlib.h ,因此在您的翻译单元中没有calloc()原型。 这将导致编译器假定calloc()的签名为int calloc(int, int) ,这不是真的。 上面的相同代码行会向您发出有关为该函数设置默认签名的警告。 使用类似于代码中的类型转换将掩盖该警告,您可能永远不会知道您错过了#include行。

请参阅图表以获得解释 在此处输入图像描述

所以你首先使用calloc创建pixel *数组pixel * 。 使用带有pixel calloc填充该数组。

代码

 pixel **pixelvalue = (pixel **) calloc(imginformation.width, sizeof(pixel)); 

pixelvalue是指向像素指针的指针 – 你的typedef。

你需要写

 pixel **pixelvalue = calloc(imginformation.width, sizeof(pixel *)); 

代替。

其他海报已正确识别出您应该以pixel*为单位而不是以pixel*为单位分配第一块内存。

但是为什么这个问题导致了段错?

在32位机器上,上面定义的像素结构需要3个字节,但指针需要32位(4个字节)。

那是,

  • sizeof(pixel) == 3
  • sizeof(pixel*) == 4

所以你只需要分配你需要的75%的内存。 访问图像的底部四分之一时,您将访问从未分配的内存。

(在某些64位平台上,问题肯定只会变得更糟。在某些16位平台上,你可能能够摆脱这种情况,尽管它仍然很邋))