Получение ошибки glibc при добавлении с использованием указателей - PullRequest
0 голосов
/ 23 ноября 2011

Я получаю следующую ошибку при компиляции моей программы в терминале:

*** glibc detected *** ./a.out: double free or corruption (fasttop): 0x089660a0 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x6ebc2)[0xb7621bc2]
/lib/i386-linux-gnu/libc.so.6(+0x6f862)[0xb7622862]
/lib/i386-linux-gnu/libc.so.6(cfree+0x6d)[0xb762594d]
./a.out[0x8048668] ./a.out[0x8048fa3]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb75cc113]
./a.out[0x80484c1]
======= Memory map: ========
08048000-0804a000 r-xp 00000000 08:06 1835029    /home/fasih/poly/a.out
0804a000-0804b000 r--p 00001000 08:06 1835029    /home/fasih/poly/a.out
0804b000-0804c000 rw-p 00002000 08:06 1835029    /home/fasih/poly/a.out
08966000-08987000 rw-p 00000000 00:00 0          [heap]
b7400000-b7421000 rw-p 00000000 00:00 0
b7421000-b7500000 ---p 00000000 00:00 0
b757f000-b759b000 r-xp 00000000 08:06 4195258    /lib/i386-linux-gnu/libgcc_s.so.1
b759b000-b759c000 r--p 0001b000 08:06 4195258    /lib/i386-linux-gnu/libgcc_s.so.1
b759c000-b759d000 rw-p 0001c000 08:06 4195258    /lib/i386-linux-gnu/libgcc_s.so.1
b75b1000-b75b3000 rw-p 00000000 00:00 0
b75b3000-b7729000 r-xp 00000000 08:06 4195237    /lib/i386-linux-gnu/libc-2.13.so
b7729000-b772b000 r--p 00176000 08:06 4195237    /lib/i386-linux-gnu/libc-2.13.so
b772b000-b772c000 rw-p 00178000 08:06 4195237    /lib/i386-linux-gnu/libc-2.13.so
b772c000-b772f000 rw-p 00000000 00:00 0
b772f000-b7757000 r-xp 00000000 08:06 4195267    /lib/i386-linux-gnu/libm-2.13.so
b7757000-b7758000 r--p 00028000 08:06 4195267    /lib/i386-linux-gnu/libm-2.13.so
b7758000-b7759000 rw-p 00029000 08:06 4195267    /lib/i386-linux-gnu/libm-2.13.so
b776c000-b776f000 rw-p 00000000 00:00 0
b776f000-b7770000 r-xp 00000000 00:00 0         [vdso]
b7770000-b778e000 r-xp 00000000 08:06 4195224   /lib/i386-linux-gnu/ld-2.13.so
b778e000-b778f000 r--p 0001d000 08:06 4195224    /lib/i386-linux-gnu/ld-2.13.so
b778f000-b7790000 rw-p 0001e000 08:06 4195224    /lib/i386-linux-gnu/ld-2.13.so
bfed6000-bfef7000 rw-p 00000000 00:00 0          [stack] Aborted

Это мой код, он, кажется, происходит в функции polyAdd, но я также получаю ошибку подтверждения при умножении, поэтому это может быть и то и другое?

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <stdbool.h>
    #include "poly.h"

    int polyDegree(struct poly *p)
    {
        return p->length-1;
    }
    struct poly *polyCreate()
    {
        struct poly *p = (struct poly *)malloc(sizeof(struct poly));
        p->coeff=(double *)malloc(sizeof(double));
        p->size=1;
        p->length=0;
        return p;

    }
    struct poly *polySetCoefficient (struct poly *p, int i, double value)
    {
        if(p == NULL)
            return;

        if(i>=p->size)
        {
            do
            {
                p->size = p->size*2;
            }while(i>=p->size);

            p->coeff = (double *)realloc(p->coeff, p->size*sizeof(double));
        }

        while(i >= p->length)
        {
            p->coeff[p->length] = 0;
            p->length++;
        }

        p->coeff[i] = value;

        return p;
    }
    struct poly *polyDelete(struct poly *p)
    {
        if (p){
        free(p);}

        return 0;
    }
    struct poly *polyCopy(struct poly *p)
    {
        struct poly *nP = polyCreate();
        nP->size =p->size;
        nP->length = p->length;
        int i = 0;
        for (i = 0; i<(nP->size);i++)
        {
            nP->coeff[i] = p->coeff[i];
        }
        return nP;
    }
    struct poly *polyAdd(struct poly *p0, struct poly *p1)
{
   int i;
   struct poly *pF = polyCreate();
   if (p0->length > p1->length)
   {
        pF = polyCopy(p0);

        for (i=0;i<p1->length;i++)
            pF->coeff[i] += p1->coeff[i];
   }
   else if (p1->length >= p0->length)
   {
        pF = polyCopy(p1);

        for (i=0;i<p0->length;i++)
            pF->coeff[i] += p0->coeff[i];
   }
   return pF;

}
    struct poly *polyPrime (struct poly *p)
    {
        struct poly *pF = polyCreate();
        pF->size = p->size;
        int i,j,k;
        int n = p->size;
        double a[n-1];
        for (i = 1; i <=n;i++)
        {
            a[i-1] = i * p->coeff[i];
        }
        for (i = 0; i < n; i++)
        {
            pF->coeff[i] = a[i];
        }
        return pF;
    }

    struct poly *polyMultiply (struct poly *p0, struct poly *p1)
    {
        struct poly *product = polyCreate();
        product->length = p0->length + p1->length - 1;
        product->size = p0->size + p1->size;
        product->coeff = (double *)malloc(product->size*sizeof(double));

        int i,j;
        for(i=0;i<product->length;i++)
            product->coeff[i] = 0;

        for(i=0;i<p0->length;i++)
            for(j=0;j<p1->length;j++)
                product->coeff[i+j] += p0->coeff[i] * p1->coeff[j];

        return product;
    }


    double polyGetCoefficient(struct poly *p, int i)
    {
        double val =p->coeff[i];
        return val;
    }
    int checkZero (double a[], int n)
    {
    int x = 0;
    for (x = 0; x < n; x++)
    {
    if (a[x] != 0)
    return 1;
    }
    return 0;
    }

    double polyEval(struct poly *p, double x)
    {
        int i,n;
        double eval=0;
        if (!p)
            return 0;
        if (p)
        n = p->length;
        if (n == 0)
            return 0;
        for (i = 0; i<=n;i++)
        {
            if (p->coeff[i] == 0)continue;
            if (i == 0)eval += p->coeff[0];
            else
                eval += p->coeff[i]* pow (x,i);
        }
        return eval;
    }

    void polyPrint (struct poly *p)
    {
        int x=0,y,z;
        int n;
        n = p->size;
        double a[p->size];
        for (x = p->size; x >= 0; x--)
        {
            a[x] = p->coeff[x];
        }

        bool check,neg,zero = true;
        if (!checkZero (a,n))
        {
            printf("0\n");
        }
        else{
        for(x=(n-1);x>=0;x--)
        {
            check = false;
            neg = false;
            if (x < (n-1) && a[x+1] == 0 && a[x] != 0 && a[x] > 0 && !zero)
                printf(" + ");
            else if (x < (n-1) && a[x+1] == 0 && a[x] != 0 && a[x] < 0 && !zero)
                {
                    printf (" - ");
                    a[x] = a[x] * -1.00;
                }
            if (a[x] == 0)
                continue;
            if (a[x] != 0.0&& x > 1)
            {
                if (a[x] == -1)printf("-x^%d",x);
                else if (a[x] == 1)printf ("x^%d",x);
                else
                printf("%gx^%d",a[x],x);
                check = true;zero = false;
            }
            else if (x == 1)
            {
                if (a[x] == 1)printf("x");
                else
                printf("%gx",a[x]);
                check = true; zero = false;
            }
            else if (x == 0)
            {
                printf("%g",a[x]);
                check = false; zero = false;
            }
            if (a[x-1] < 0 && x > 0){
                printf (" - ");a[x-1] = a[x-1] * -1.00;}
            else if (x > 0&& a[x-1] != 0)printf(" + ");
        }
        printf("\n");}
    }

Ответы [ 2 ]

3 голосов
/ 23 ноября 2011

Это ошибка:

for (i = 0; i<=n;i++)
{
    if (p->coeff[i] == 0)continue;
    if (i == 0)eval += p->coeff[0];
    else
        eval += p->coeff[i]* pow (x,i);
}

Индексы массивов в C работают от 0 до n-1; i<=n будет оценивать p->coeff[n], что является данными мусора. (Это также форматирование мусора - я бы предложил запустить всю программу через indent(1); ядро ​​Linux использует параметры indent(1): -npro -kr -i8 -ts8 -sob -l80 -ss -ncs -cp1 -il0; мне это нравится.)

Вот та же ошибка в несколько ином виде:

n = p->size;
double a[p->size];
for (x = p->size; x >= 0; x--)
{
    a[x] = p->coeff[x];
}

Я ожидаю, что p->size - это размер массива, а не самый большой индекс массива.

Вот другая ошибка:

    if (a[x] != 0.0&& x > 1)
    {

Вы можете быть шокированы тем, как редко 0.0 равно 0.0 в арифметике с плавающей запятой. Никогда не делайте прямого сравнения, как это - вместо этого проверьте, достаточно ли близка к нулю разница, чтобы вы могли назвать ее нулевой. (Здесь нет ничего о 0.0 - сравнения с плавающей запятой по всем направлениям нужно проводить осторожно.)

2 голосов
/ 23 ноября 2011

В подобных ситуациях может стоить запустить вашу программу через valgrind:

valgrind ./your_program

Это, вероятно, сможет более или менее точно определить, где происходят какие-либо ошибочные записи.Исправьте то, что вы найдете, снова запустите valgrind и убедитесь, что вы их все получили.Обратите внимание, что valgrind не будет, по крайней мере в прошлый раз, когда я проверял, предупреждать вас о доступе за пределы допустимого массива.

Valgrind доступен как источник здесь , но я рекомендуюиспользуя выбранный в вашей операционной системе метод управления пакетами, чтобы получить его, если это вообще возможно.

...