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

发布于 2024-07-26 10:16:22 字数 3446 浏览 8 评论 0原文

我有一个程序,基本上看起来像:

    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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

_畞蕅 2024-08-02 10:16:22

如果您在 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.

故事还在继续 2024-08-02 10:16:22

从这里看起来,您正在尝试创建一个链接列表:

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

但是,您使用它的方式,您正在创建一个数组:

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

这让我不清楚您真正想要做什么。 您似乎也从未初始化 link 成员,所以也许您试图将其视为链表并从末端进入超空间?

从您的代码中我看起来很奇怪的其他事情:

  1. n1n2 从未收到您似乎不使用 apt 变量的 任何
  2. ab 都不会被释放,
  3. 你也不会检查 malloc 的返回值,也许你分配失败了?

不过,这些都不是真正的“确凿证据”,也许您应该尝试将样本范围缩小到有效但仍然会导致问题的东西?

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?

Other things that look weird to me from your code:

  1. n1 and n2 never receive a value
  2. you don't seem to use the apt variable for anything
  3. a and b are never freed
  4. you never check the return value from malloc, 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?

写给空气的情书 2024-08-02 10:16:22

设置标志

在发布之前,请考虑设置以下标志:
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

接下来您需要的是 动态数组
请构建您的代码! 构建这样一个数组的函数可以被抽象。

你是从右向左读的吗? 无意冒犯,但注释位于代码之前。

/* comment */
code

不要成为明星程序员! 如果某件事需要不止一颗星,请创建一个函数。

Set the flags

Before posting, consider setting the following flags:
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.

丶情人眼里出诗心の 2024-08-02 10:16:22
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;
} 

在这里,您正在访问 cplptr2 从 n1 到 n1 + n2 的索引(j),但按照
您的分配cplptr2 = (cpls *) malloc(n2*sizeof(cpls)),索引应该从0开始
至n2-1。 对于 cplptr2,最好使用 j-n1 而不是 j。

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. better use j-n1 instead of j for cplptr2.

北方。的韩爷 2024-08-02 10:16:22

我认为在实际程序中,您在某处设置了 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.

羁绊已千年 2024-08-02 10:16:22

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

You haven't initialized n1 or n2 anywhere, they could be zero or even negative.

茶花眉 2024-08-02 10:16:22
  a = malloc(n1 * sizeof(int));
  apt = &a[0];

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

  b = malloc(n1 * sizeof(int));
  apt = &b[0]; // <-- should be bpt, bug ?
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文