【发布时间】:2012-11-05 03:18:09
【问题描述】:
根据我之前的question(非常感谢 Jonathan Leffler),我编辑了我的代码(后两个代码块),但遇到了一个相当奇怪的问题。
以下一个意外中断...
void free_array(array_info *A)
{
int i;
for(i = 0; i < (A->height); ++i)
{
printf("About to free: %x\n", A->dat_ptr[i]);//for debugging purposes
free(A->dat_ptr[i]);
printf("Freed row %i\n", i);//for debugging purposes
}
free(A->dat_ptr);
}
我最初测试了create_array,然后直接测试了free_array,它在相当大的数组 (10^8) 上完美运行。但是,当我在两者之间进行计算然后尝试free() 数组时,我得到一个访问冲突异常(c00000005)。当我调试它时,我注意到如果我在“free_array”循环中有一个断点并单独执行每一行,程序每次都会完美执行。但是,编译后的代码永远不会自己运行超过我的第二个数组的第 6 行。我关闭了编译器中的所有优化,执行时仍然报错。
附加信息
typedef struct {
int height;
int width;
int bottom;//position of the bottom tube/slice boundary
unsigned int** dat_ptr;//a pointer to a 2d array
} array_info;
dat_ptr 现在是一个正确的 2D 指针。创建要放入结构中的数组的create_array 函数是(我已剥离 NULL 检查以确保可读性):
int create_array(array_info *A)
{
int i;
unsigned int **array = malloc(sizeof(*array) * A->height);
for (i = 0; i < A->height; ++i)
{
array[i] = malloc(sizeof(**array) * A->width);
}
A->dat_ptr = array;
return 0;
}
此功能完全按预期工作。
更多附加信息
在 Jonathan、Chris 和 rharrison33 的回复之后添加
非常感谢乔纳森,通过你的每一篇文章,我发现了很多关于编程的知识:) 我终于找到了罪魁祸首。导致异常的代码如下:
void fill_number(array_info* array, int value, int x1, int y1, int x2, int y2)//fills a rectangular part of the array with `value`
{
int i, j;
for(i=y1 ; ((i<=y2)&&(i<array->height)) ; i++)//start seeding the values by row (as in vertically)
{
for(j=x1 ; ((i<=x2)&&(i<array->width)) ; j++)//seed the values by columns (as in horizontally)
{
array->dat_ptr[i][j]=value;
}
}
}
而((i<=x2)&&(i<=array->width)) 并没有像我预期的那样被评估(克里斯·多德,你是对的)。我认为它会按该顺序评估这两个条件,或者如果其中一个为“FALSE”则停止,而与它们的顺序无关。然而,事实证明它不是那样工作的,它只是拒绝正确评估(i<array->width) 部分。另外,我认为它会在尝试访问数组范围之外的内存时触发异常,但事实并非如此。总之,
我把代码改成:
void fill_number(array_info* array, int value, int x1, int y1,
int x2, int y2)
{
int i, j;
if(y1>=array->height){ y1=array->height-1;}
if(y2>=array->height){ y1=array->height-1;}
if(x1>=array->width) { x2=array->width-1;}
if(x2>=array->width) { x2=array->width-1;}
for(i=y1 ; i<=y2 ; i++)//start seeding the values by row
{
for(j=x1 ; j<=x2 ; j++)//seed the values by column
{
array->dat_ptr[i][j]=value;
}
}
}
现在它可以工作了。 if()s 块在那里,因为与其他代码相比,我不会经常调用该函数,并且我需要一种视觉方式来提醒我检查在那里。
再次感谢 Jonathan Leffler、Chris Dodd 和 rharrison33 :)
【问题讨论】:
-
听起来像您在
create_array和free_array调用之间执行的“计算”会注销其中一个数组的末尾(因此当y >= A->width或 @987654339 时存储在A->dat_ptr[x][y]中@.) 要么使用内存检查器 (valgrind),要么手动为每个数组访问添加边界检查。
标签: c free access-violation