2

我有一个基本上看起来像这样的程序:

    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(cpplptr) 似乎会导致分段错误。它只被调用一次,我在 malloc() 调用 cplptr 之后和 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 和步骤找不到当前函数的边界

有没有另一种方法来实现类似的东西来避免分段错误?

感谢一百万您的建议!知道发生了什么吗?

4

7 回答 7

3

如果您在 free() 上遇到崩溃,这很可能是由于堆损坏 - 您正在写入超出已分配内存块的末尾、释放指针两次或类似情况。

Valgrind是在 Linux 上调试此类问题的好工具。

于 2009-06-28T00:27:16.143 回答
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;
} 

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

于 2011-08-04T09:22:31.077 回答
1

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

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. n1并且n2永远不会收到价值
  2. 您似乎没有将apt变量用于任何事情
  3. a并且b永远不会被释放
  4. 您从不检查 的返回值malloc,也许您分配失败?

不过,这一切都不是真正的“确凿证据”,也许您应该尝试将样本范围缩小到可行的范围内,但仍然会导致问题?

于 2009-06-28T00:35:56.143 回答
1

设置标志

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

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

于 2009-06-28T01:06:00.387 回答
0

我假设在实际程序中,您在某处设置了 n1 和 n2 ?

此外,在循环外分配 cplptr 而不是检查 i==0。

您可能有错字,您从未设置 bpt,但设置了两次。

于 2009-06-28T00:32:27.617 回答
0

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

于 2009-06-28T00:33:52.963 回答
0
  a = malloc(n1 * sizeof(int));
  apt = &a[0];

  b = malloc(n1 * sizeof(int));
  apt = &b[0]; // <-- should be bpt, bug ?
于 2009-06-28T00:34:52.993 回答