我的程序中存在一个小内存访问问题,我没有找到错误,也许有人可以帮助我。
我创建了一个新类型来存储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 space作为函数的参数,而不是返回值。
感谢您的帮助!
格尔茨
答案 0 :(得分:3)
你并没有真正制作一个2D数组,你正在制作一个指向像素数组的指针数组。这意味着您的第一个calloc
调用应该为指针分配足够的空间,而不是像素:
pixel **pixelvalue = calloc(imginformation.width, sizeof(pixel *));
您没有使用某种语言标记您的问题,但假设它是C(基于您的typedef
,这在C ++中是不必要的),您不应该转换{{的返回值1}}。这样做可以隐藏calloc()
的错误,这些错误可能会让你在路上遇到麻烦。
修改强>
你问了几个跟进问题。我想,第一个答案已经得到了很好的回答,但我会试着总结一下。你进行分配的方式是,你首先要分配一个指针数组 - 这些指针中的每一个都将指向数组的一行。然后需要分配行本身 - 每个#include
对象的空间都在那里,而指向行的指针存储在第一个指针数组中。
你的第二个问题,来自pixel
的返回值非常简单。如果转换返回值,则可以隐藏自己的隐式声明错误。由于calloc()
的返回类型为calloc
,因此您执行以下操作:
void *
一切都很好用。现在假设您没有包含my_ptr = calloc(1, 2);
,因此您的翻译单元中没有stdlib.h
的原型。这将导致编译器假定calloc()
的签名为calloc()
,这不是真的。上面的相同代码行会向您发出有关为该函数设置默认签名的警告。使用类似于代码中的类型转换将掩盖该警告,您可能永远不会知道您错过了int calloc(int, int)
行。
答案 1 :(得分:1)
请参阅图表以获取解释
所以你首先使用calloc创建pixel *
数组。使用calloc
pixel
填充该数组。
答案 2 :(得分:0)
代码
pixel **pixelvalue = (pixel **) calloc(imginformation.width, sizeof(pixel));
pixelvalue
是指向像素指针的指针 - 你的typedef。
你需要写
pixel **pixelvalue = calloc(imginformation.width, sizeof(pixel *));
代替。
答案 3 :(得分:0)
其他海报已正确识别出您应该以{{1}}为单位而不是以pixel*
为单位分配第一块内存。
但是为什么这个问题导致了段错?
在32位机器上,上面定义的像素结构需要3个字节,但指针需要32位(4个字节)。
即,
pixel
sizeof(pixel) == 3
所以你只需要分配75%的内存。访问图像的底部四分之一时,您将访问从未分配过的内存。
(在某些64位平台上,问题肯定会变得更糟。在某些16位平台上,你可能能够摆脱这种情况,尽管它仍然很邋))