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

C 通过在2D数组中写入来分割错误,c,memory,segmentation-fault,calloc,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(imginformat

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

我创建了一个新类型来存储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));
}
在这个函数中,我尝试用

pixelvalue[i][j].r = (unsigned char)fgetc(in);
这里我得到了内存访问错误,我做错了什么

编辑

嗨,首先很抱歉,我昨天有点累了:)

为了理解,我创建了一个像素数组,元素指向另一个像素数组?类似于
[指向另一个1D阵列像素]

像素
**pixelvalue=calloc(imginformation.width,sizeof(像素*)
I创建
imginformation.width
type pixel的指针数,每个指针都显示到pixel,对吗

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

@carl norum你说的是什么意思:

“您不应该强制转换calloc()的返回值。这样做可能会 用#include隐藏可能会回来咬你的虫子 道路”

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

谢谢你的帮助


Greetz

你不是在制作一个2D数组,而是在制作一个指向像素数组的指针数组。这意味着您的第一次
calloc
调用应该为指针分配足够的空间,而不是像素:

pixel **pixelvalue = calloc(imginformation.width, sizeof(pixel *));
您没有用语言标记您的问题,但是假设它是C(基于您的
typedef
,这在C++中是不必要的),您不应该强制转换
calloc()的返回值。这样做可以隐藏带有
#include
的bug,这些bug可能会在将来再次咬到你

编辑:

你问了几个后续问题。我认为,第一个问题已经被其他几个答案很好地回答了,但我将尝试总结一下。在进行分配的方式中,首先要分配一个指针数组——每个指针都指向数组中的一行。然后需要为行本身分配空间——每个
像素的空间都在那里,指向行的指针存储在第一个指针数组中

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

my_ptr = calloc(1, 2);
一切都很顺利。现在假设您没有包含
stdlib.h
,因此在翻译单元中没有
calloc()
的原型。这将导致编译器假定
calloc()
的签名为
intcalloc(int,int)
,这是不正确的。上面的同一行代码会向您发出警告,提醒您不要为该函数假定默认签名。在代码中使用类似的类型转换将屏蔽该警告,并且您可能永远不会知道您丢失了
#include
行。

代码

pixel **pixelvalue = (pixel **) calloc(imginformation.width, sizeof(pixel)); 
pixelvalue
是指向像素的指针-您的typedef

你需要写作

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

相反。

请参见图表以了解说明


因此,首先使用calloc创建
pixel*
的数组。使用
calloc
pixel
填充该数组。其他海报已正确识别您应该以
pixel*
为单位分配第一块内存,而不是以
pixel
为单位

但为什么这个问题会导致segfault

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

就是

  • sizeof(像素)==3
  • 但是
    sizeof(pixel*)==4
因此,您只分配了所需内存的75%。当访问映像的底部四分之一时,您将访问从未分配的内存


(在某些64位平台上,问题肯定只会变得更糟。在某些16位平台上,您可能可以解决这个问题,尽管它仍然很草率)

您好,谢谢您的解决方案运行良好。现在我有一些理解上的问题,请看我的编辑。谢谢。是的,你的权利以及@carl norum。请看我编辑,我很抱歉,我理解正确了吗?谢谢,这帮了大忙!首先,我创建所有指针,例如高度和每个元素显示为一个像素的宽度。非常感谢。Taz-使用诊断图来理顺你头脑中的事物是的,应该是。你知道为什么会发生这个问题,对吗?(参见Ed Heal的精细图表)
pixel **pixelvalue = calloc(imginformation.width, sizeof(pixel *));