Программа на C работает в Cygwin, но не в Linux (Malloc) - PullRequest
1 голос
/ 04 мая 2010

У меня ошибка выделения кучи, которую я не могу обнаружить в своем коде, который обнаружен в vanguard / gdb в Linux, но отлично работает в среде Windows Cygwin. Я понимаю, что Linux может быть более жестким с распределением кучи, чем Windows, но я действительно хотел бы получить ответ, который обнаружит проблему / возможное решение. Я также знаю, что я не должен типизировать malloc в C, но это привычка, которая не меняет мою проблему. Моя программа на самом деле без ошибок компилируется как в Linux, так и в Windows, но когда я запускаю ее в Linux, я получаю страшно выглядящий результат:

malloc.c: 3074: sYSMALLOc: утверждение `(old_top == (((mbinptr) (((char *) & ((av) -> bins [((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size)> = (unsigned long) ((((__buildin_offsetof (struct malloc_chunk, fd_nextsize)) + ((2 * (sizeof (size_t))) - 1)) & ~ ((2 * (sizeof (size_t))) - 1))) && ((old_top) -> size & 0x1) && ((unsigned long) old_end & pagemask) == 0) 'не удалось. Отменено

Прикрепленный фрагмент из моего кода, на который указывает ошибка для проверки:

/* Main */

int main(int argc, char * argv[]) {

    FILE *pFile;  
    unsigned char *buffer;  
    long int lSize;  

    pFile = fopen ( argv[1] , "r" );
    if (pFile==NULL) {fputs ("File error on arg[1]",stderr); return 1;}

    fseek (pFile , 0 , SEEK_END);
    lSize = ftell (pFile);
    rewind (pFile);

    buffer = (char*) malloc(sizeof(char) * lSize+1);
    if (buffer == NULL) {fputs ("Memory error",stderr); return 2;}

    bitpair * ppairs = (bitpair *) malloc(sizeof(bitpair) * (lSize+1));

    //line 51 below
    calcpair(ppairs, (lSize+1));

    /* irrelevant stuff */

    fclose(pFile);
    free(buffer);
    free(ppairs);  
}

typedef struct {  
long unsigned int a;  //not actual variable names...  Yes I need them to be long unsigned  
long unsigned int b;  
long unsigned int c;  
long unsigned int d;  
long unsigned int e;  
} bitpair;  

void calcpair(bitpair * ppairs, long int bits);

void calcPairs(bitpair * ppairs, long int bits) {

    long int i, top, bot, var_1, var_2;
    int count = 0;

    for(i = 0; i < bits; i++) {

        top = 0;

        ppairs[top].e = 1;

        do {
            bot = count;
            count++;
        } while(ppairs[bot].e != 0);

        ppairs[bot].e = 1;

        var_1 = bot;
        var_2 = top;

        bitpair * bp = &ppairs[var_2];
        bp->a = var_2;
        bp->b = var_1;
        bp->c = i;

        bp = &ppairs[var_1];
        bp->a = var_2;
        bp->b = var_1;
        bp->c = i;

    }

    return;
}

отчеты gdb: free (): неверный указатель: 0x0000000000603290 *

valgrind сообщает следующее сообщение 5 раз перед выходом из-за сигнала 11 "VALGRIND INTERNAL ERROR" (SIGSEGV):
Неверное чтение размера 8
== 2727 == в 0x401043: calcPairs (in / home / user / Documents / 5-3 / ubuntu test / main)
== 2727 == по 0x400C9A: основной (main.c: 51)
== 2727 == Адрес 0x5a607a0 не является стековым, malloc или (недавно) свободным

Ответы [ 4 ]

1 голос
/ 08 мая 2010

похоже на переполнение массива

Ничто не мешает этому циклу превысить конец массива ppair:

    do { 
        bot = count; 
        count++; 
    } while(ppairs[bot].e != 0); 

Тем более что эта строка перезапишет ваш конечный ноль:

ppairs[bot].e = 1;

Попробуйте вместо этого:

    do { 
        bot = count; 
        count++; 
    } while((bot < bits) && (ppairs[bot].e != 0)); 

С уважением, Том

1 голос
/ 04 мая 2010

Похоже, вы ожидаете, что malloc вернет предварительно обнуленную память.

    do {
        bot = count;
        count++;
    } while(ppairs[bot].e != 0);

может легко добраться до конца ваших пар, не найдя нулевых пар [бот] .e

Вы хотите использовать calloc вместо malloc, который очищает память перед возвратом.

bitpair * ppairs = (bitpair *) calloc(sizeof(bitpair) * (lSize+1));
1 голос
/ 04 мая 2010

По дикой догадке ftell возвращает -1, а malloc не нравится, когда его просят выделить ноль байтов. Поведение malloc (0) зависит от реализации в C.

0 голосов
/ 04 мая 2010

Ваш второй вызов malloc никогда не проверяется на возвращаемое значение. Измените его так, чтобы он больше походил на первый, например:

bitpair * ppairs = (bitpair *) malloc(sizeof(bitpair) * (lSize+1));
if (ppairs == NULL) {fputs ("Memory error",stderr); free(buffer); return 3;}

Кроме того, помните, malloc ожидает size_t (определение которого зависит от реализации) для аргумента. Убедитесь, что при передаче (sizeof(bitpair) * (lSize+1)) в malloc вы не переполняете size_t (если size_t определено как unsigned int, вы можете столкнуться с проблемами, поскольку lSize является long).

...