C 循环中 malloc/free 出现分段错误
我有一个程序,基本上看起来像:
typedef struct cpl_def
{
int A;
int B;
int OK;
struct cpls *link;
}cpls;
int main(void)
{
int n1, n2;
int num = 300; /* say */
int *a;
a = NULL;
int *apt;
int *b;
b = NULL;
int *bpt;
cpls *cplptr;
cplptr = NULL;
int i, j;
for (i=0; i < 2000; i++)
{
if (i == 0)
{
cplptr = (cpls *) malloc(num*sizeof(cpls) ); /* create the structure */
initalize(cplptr);
}
/*
...operations on cplptr ... */
FOO(cplptr);
/*
...determine I need a subset of size n1 (a positive integer of size n1 which changes during the loop) entries from cplptr ... */
n1 = FOO2(cplptr);
n2 = FOO3(cplptr);
/*
...figure out the values of A, B for additional n2 entries into cplptr ...
*/
cplptr2 = (cpls *) malloc(n2*sizeof(cpls) ); /* a second structure to store additional entries */
/* .... operations on cplptr2 ...*/
/* ...copy subset of n1 entries from cplptr into dynamically allocated arrays a,b of size n1... */
a = malloc(n1 * sizeof(int));
apt = &a[0];
b = malloc(n1 * sizeof(int));
bpt = &b[0];
for (j=0; j < num; j++)
{
if (cplptr[j].OK==1)
{
(*apt++) = cplptr[j].a;
(*bpt++) = cplptr[j].b;
}
}
free(cplptr); /* free the first structure */
cplptr = (cpls *) malloc((n1+n2)*sizeof(cpls) ); /* redeclare the first structure to reflect the proper sizes */
for (j = 0; j < n1; j++) /* transfer a subset of size n1 to the first structure */
{
cplptr[j].a = a[j];
cplptr[j].b = b[j];
cplptr[j].OK = 1;
}
for (j = n1; j < n1 + n2; j++) /* transfer things to the first structure */
{
cplptr[j].a = cplptr2[j].a;
cplptr[j].b = cplptr2[j].b;
cplptr[j].OK = cplptr2[j].OK;
}
free(a)
free(b)
free(cplptr2); /* free the second structure */
} /* End iteration i
} /* End main() */
这只是骨架形式,但希望它能提供足够的图片。 无论如何,它通常运行良好,但对于 n1、n2 的某些值, free(cplptr) 似乎会导致分段错误。 它只被调用一次,并且我在对 cplptr 的 malloc() 调用之后和 cplptr 的相应 free() 之前检查地址。
....
cplptr = (cpls *) malloc(num*sizeof(cpls) );
printf("fine to this %p\n", &cplptr[0]);
...
printf("fine to this %p\n", &cplptr[0]);
free(cplptr) <- segmentation fault happens here.
地址匹配,这意味着 free() 应该释放它应该释放的内容,对吧? gdb 给出 程序收到信号 SIGSEGV,分段错误。 0xb7ce179b 在 ?? () 来自 /lib/tls/i686/cmov/libc.so.6 和步骤 找不到当前函数的边界
是否有另一种方法来实现类似的方法以避免分段错误?
感谢您的建议一百万! 知道发生了什么事吗?
I have a program that basically looks like:
typedef struct cpl_def
{
int A;
int B;
int OK;
struct cpls *link;
}cpls;
int main(void)
{
int n1, n2;
int num = 300; /* say */
int *a;
a = NULL;
int *apt;
int *b;
b = NULL;
int *bpt;
cpls *cplptr;
cplptr = NULL;
int i, j;
for (i=0; i < 2000; i++)
{
if (i == 0)
{
cplptr = (cpls *) malloc(num*sizeof(cpls) ); /* create the structure */
initalize(cplptr);
}
/*
...operations on cplptr ... */
FOO(cplptr);
/*
...determine I need a subset of size n1 (a positive integer of size n1 which changes during the loop) entries from cplptr ... */
n1 = FOO2(cplptr);
n2 = FOO3(cplptr);
/*
...figure out the values of A, B for additional n2 entries into cplptr ...
*/
cplptr2 = (cpls *) malloc(n2*sizeof(cpls) ); /* a second structure to store additional entries */
/* .... operations on cplptr2 ...*/
/* ...copy subset of n1 entries from cplptr into dynamically allocated arrays a,b of size n1... */
a = malloc(n1 * sizeof(int));
apt = &a[0];
b = malloc(n1 * sizeof(int));
bpt = &b[0];
for (j=0; j < num; j++)
{
if (cplptr[j].OK==1)
{
(*apt++) = cplptr[j].a;
(*bpt++) = cplptr[j].b;
}
}
free(cplptr); /* free the first structure */
cplptr = (cpls *) malloc((n1+n2)*sizeof(cpls) ); /* redeclare the first structure to reflect the proper sizes */
for (j = 0; j < n1; j++) /* transfer a subset of size n1 to the first structure */
{
cplptr[j].a = a[j];
cplptr[j].b = b[j];
cplptr[j].OK = 1;
}
for (j = n1; j < n1 + n2; j++) /* transfer things to the first structure */
{
cplptr[j].a = cplptr2[j].a;
cplptr[j].b = cplptr2[j].b;
cplptr[j].OK = cplptr2[j].OK;
}
free(a)
free(b)
free(cplptr2); /* free the second structure */
} /* End iteration i
} /* End main() */
This is just the skeletal form but it hopefully provides enough of a picture. ANyhow it generally runs fine, but for some values of n1, n2, the free(cplptr) seems to cause a segmentation fault. It's only called once, and I check the address after the malloc() call to cplptr and before the corresponding free() for cplptr.
....
cplptr = (cpls *) malloc(num*sizeof(cpls) );
printf("fine to this %p\n", &cplptr[0]);
...
printf("fine to this %p\n", &cplptr[0]);
free(cplptr) <- segmentation fault happens here.
The addresses match, meaning free() should be freeing what it's supposed to, right??
gdb gives
Program received signal SIGSEGV, Segmentation fault.
0xb7ce179b in ?? () from /lib/tls/i686/cmov/libc.so.6
and step
Cannot find bounds of current function
Is there another way to implement something like that avoids the segmentation faults?
Thanks a million for your suggestions!
Any idea what's going on??
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果您在 free() 上遇到崩溃,这很可能是由于堆损坏 - 您正在超出分配的内存块的末尾写入,释放指针两次,或类似的情况。
Valgrind 是在 Linux 上调试此类问题的绝佳工具。
If you're hitting a crash on free(), this is most likely due to heap corruption - you are writing beyond the end of an allocated block of memory, freeing a pointer twice, or similar.
Valgrind is a great tool to debug these sort of issues on Linux.
从这里看起来,您正在尝试创建一个链接列表:
但是,您使用它的方式,您正在创建一个数组:
这让我不清楚您真正想要做什么。 您似乎也从未初始化
link
成员,所以也许您试图将其视为链表并从末端进入超空间?从您的代码中我看起来很奇怪的其他事情:
n1
和n2
从未收到您似乎不使用apt
变量的 任何a
和b
都不会被释放,malloc
的返回值,也许你分配失败了?不过,这些都不是真正的“确凿证据”,也许您应该尝试将样本范围缩小到有效但仍然会导致问题的东西?
It looks like from this, you are trying to create a linked list:
But then, the way you use it, you are creating an array:
This makes it unclear to me what you are really trying to do. You never seem to initialise the
link
member either, so maybe you are trying to treat it like a linked list and walking off the end into hyperspace?Other things that look weird to me from your code:
n1
andn2
never receive a valueapt
variable for anythinga
andb
are never freedmalloc
, maybe you are failing an allocation?None of this is really a "smoking gun" though, maybe you should try to narrow down your sample to something that works, but still causes the issue?
设置标志
在发布之前,请考虑设置以下标志:
cc -Werror -Wall smth.c
接下来您需要的是 动态数组
请构建您的代码! 构建这样一个数组的函数可以被抽象。
你是从右向左读的吗? 无意冒犯,但注释位于代码之前。
不要成为明星程序员! 如果某件事需要不止一颗星,请创建一个函数。
Set the flags
Before posting, consider setting the following flags:
cc -Werror -Wall smth.c
Next thing what you need is a dynamic array
Please structure your code! The functions to build such an array could be abstracted.
Do you read from right to left? No offense, but comments go before the code.
Don't be a star-programmer! If something needs more than one star, make a function.
在这里,您正在访问 cplptr2 从 n1 到 n1 + n2 的索引(j),但按照
您的分配
cplptr2 = (cpls *) malloc(n2*sizeof(cpls))
,索引应该从0开始至n2-1。 对于 cplptr2,最好使用 j-n1 而不是 j。
Here you are accessing the index(j) for cplptr2 going from n1 to n1 + n2 but as per
your allocation
cplptr2 = (cpls *) malloc(n2*sizeof(cpls))
, the index should go from 0to n2-1. better use j-n1 instead of j for cplptr2.
我认为在实际程序中,您在某处设置了 n1 和 n2 吗?
另外,在循环外部分配 cplptr 而不是检查 i==0。
你可能有一个拼写错误,你没有设置bpt,而是设置了两次apt。
I presume that in the real program, you set n1 and n2 somewhere?
Also, allocate cplptr outside the loop instead of checking i==0.
You may have a typo, you never set bpt, but set apt twice.
您尚未在任何地方初始化 n1 或 n2,它们可能为零甚至负数。
You haven't initialized n1 or n2 anywhere, they could be zero or even negative.