简体   繁体   English

C中循环出现malloc / free时出现分段错误

[英]Segmentation fault when malloc/free appear in loop in C

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. 通常,它通常运行良好,但是对于某些值n1,n2,free(cplptr)似乎会导致分段错误。 It's only called once, and I check the address after the malloc() call to cplptr and before the corresponding free() for 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.

The addresses match, meaning free() should be freeing what it's supposed to, right?? 地址匹配,这意味着free()应该释放它应有的功能,对吗? gdb gives Program received signal SIGSEGV, Segmentation fault. gdb给出程序接收信号SIGSEGV,分段错误。 0xb7ce179b in ?? 0xb7ce179b in ?? () from /lib/tls/i686/cmov/libc.so.6 and step Cannot find bounds of current function ()从/lib/tls/i686/cmov/libc.so.6中,并找到当前函数的边界

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?? 知道发生了什么吗?

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. 如果您在free()上遇到崩溃,则很可能是由于堆损坏-您正在超出分配的内存块末尾进行写入,两次释放指针或类似操作。

Valgrind is a great tool to debug these sort of issues on Linux. Valgrind是在Linux上调试此类问题的好工具。

It looks like from this, you are trying to create a linked list: 看起来像这样,您正在尝试创建一个链表:

typedef struct cpl_def
{
  int A;
  int B;
  int OK; 
  struct cpls *link;      
} cpls;

But then, the way you use it, you are creating an array: 但是,然后,您使用它的方式将创建一个数组:

cplptr = (cpls *) malloc(num*sizeof(cpls) );
...
cplptr[j].a = a[j];

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? 您似乎也从未初始化link成员,因此也许您正在尝试将其视为链接列表,然后从头到尾进入超空间?

Other things that look weird to me from your code: 从您的代码来看,其他令我感到奇怪的事情是:

  1. n1 and n2 never receive a value n1n2永远不会收到值
  2. you don't seem to use the apt variable for anything 你似乎什么都不用apt变量
  3. a and b are never freed ab永远不会释放
  4. you never check the return value from malloc , maybe you are failing an allocation? 您从不检查malloc的返回值,也许您分配失败?

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? 不过,这都不是真正的“吸烟枪”,也许您应该尝试将样本缩小到可以使用的范围,但仍然会引起问题?

Set the flags 设置标志

Before posting, consider setting the following flags: cc -Werror -Wall smth.c 发布之前,请考虑设置以下标志:cc -Werror -Wall smth.c

smth.c: In function 'main':
smth.c:13: error: 'NULL' undeclared (first use in this function)
smth.c:13: error: (Each undeclared identifier is reported only once
smth.c:13: error: for each function it appears in.)
cc1: warnings being treated as errors
smth.c:29: warning: implicit declaration of function 'malloc'
smth.c:29: warning: incompatible implicit declaration of built-in function 'malloc'
smth.c:37: error: 'cplptr2' undeclared (first use in this function)
smth.c:37: warning: incompatible implicit declaration of built-in function 'malloc'
smth.c:53: error: 'struct cpl_def' has no member named 'a'
smth.c:54: error: 'struct cpl_def' has no member named 'b'
smth.c:57: warning: implicit declaration of function 'free'
smth.c:63: error: 'struct cpl_def' has no member named 'a'
smth.c:64: error: 'struct cpl_def' has no member named 'b'
smth.c:69: error: 'struct cpl_def' has no member named 'a'
smth.c:70: error: 'struct cpl_def' has no member named 'b'
smth.c:76:12: error: "/*" within comment
smth.c:77: warning: control reaches end of non-void function

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. 没有冒犯,但注释在代码之前。

/* comment */
code

Don't be a star-programmer! 不要成为明星程序员! If something needs more than one star, make a function. 如果某物需要一颗以上的星星,请执行一项功能。

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;
} 

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 0 to n2-1. 在这里,您正在访问从n1到n1 + n2的cplptr2的索引(j),但是根据您的分配cplptr2 = (cpls *) malloc(n2*sizeof(cpls)) ,索引应该从0到n2-1。 better use j-n1 instead of j for cplptr2. 对于cplptr2,最好使用j-n1而不是j。

I presume that in the real program, you set n1 and n2 somewhere? 我认为在实际程序中,您将n1和n2设置在某个位置?

Also, allocate cplptr outside the loop instead of checking i==0. 另外,在循环外分配cplptr而不是检查i == 0。

You may have a typo, you never set bpt, but set apt twice. 您可能有错别字,您从未设置过bpt,而是设置了两次apt。

您尚未在任何地方初始化n1或n2,它们可能为零甚至是负数。

  a = malloc(n1 * sizeof(int));
  apt = &a[0];

  b = malloc(n1 * sizeof(int));
  apt = &b[0]; // <-- should be bpt, bug ?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM