Ошибка сегментации, когда malloc / free появляются в цикле в C - PullRequest
1 голос
/ 28 июня 2009

У меня есть программа, которая в основном выглядит так:

    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), кажется, вызывает ошибку сегментации. Он вызывается только один раз, и я проверяю адрес после вызова malloc () cplptr и перед соответствующим free () для 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.

Адреса совпадают, то есть free () должен освобождать то, что должен, верно? GDB дает Программа получила сигнал SIGSEGV, Ошибка сегментации. 0xb7ce179b в ?? () из /lib/tls/i686/cmov/libc.so.6 и шаг Не удается найти границы текущей функции

Есть ли другой способ реализовать что-либо подобное, чтобы избежать ошибок сегментации?

Спасибо миллион за ваши предложения! Есть идеи, что происходит ??

Ответы [ 7 ]

3 голосов
/ 28 июня 2009

Если вы сталкиваетесь с падением free (), это, скорее всего, связано с повреждением кучи - вы пишете за пределами выделенного блока памяти, освобождаете указатель дважды или подобное.

Valgrind - отличный инструмент для устранения подобных проблем в Linux.

1 голос
/ 04 августа 2011
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;
} 

Здесь вы получаете доступ к индексу (j) для cplptr2, идущему от n1 до n1 + n2, но согласно Ваше распределение cplptr2 = (cpls *) malloc(n2*sizeof(cpls)), индекс должен идти от 0 на п2-1. лучше использовать j-n1 вместо j для cplptr2.

1 голос
/ 28 июня 2009

Установить флаги

Перед публикацией рассмотрите возможность установки следующих флагов: 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

Не будь звездным программистом! Если что-то требует более одной звезды, создайте функцию.

1 голос
/ 28 июня 2009

Похоже, из этого вы пытаетесь создать связанный список:

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, может быть, вы ошибаетесь при выделении?

Ничего из этого не является "курящим пистолетом", хотя, может быть, вам следует попытаться сузить ваш образец до чего-то, что работает, но все же вызывает проблему?

0 голосов
/ 28 июня 2009
  a = malloc(n1 * sizeof(int));
  apt = &a[0];

  b = malloc(n1 * sizeof(int));
  apt = &b[0]; // <-- should be bpt, bug ?
0 голосов
/ 28 июня 2009

Вы нигде не инициализировали n1 или n2, они могут быть нулевыми или даже отрицательными.

0 голосов
/ 28 июня 2009

Я предполагаю, что в реальной программе вы устанавливаете n1 и n2 где-нибудь?

Кроме того, выделите cplptr вне цикла вместо проверки i == 0.

У вас может быть опечатка, вы никогда не устанавливаете bpt, но устанавливаете apt дважды.

...