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

时间:2012-02-03 00:04:17

标签: c memory segmentation-fault calloc

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

我创建了一个新类型来存储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作为函数的参数,而不是返回值。

感谢您的帮助!

格尔茨

4 个答案:

答案 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)

请参阅图表以获取解释enter image description here

所以你首先使用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位平台上,你可能能够摆脱这种情况,尽管它仍然很邋))