Вопрос

Я внедряю полиномиальный алгоритм разделения и завоевать полином malloc работать. Когда я запускаю программу, она выделяет кучу вещей, проверяет некоторые вещи, а затем отправляет size/2 к алгоритму. Затем, когда я ударил malloc Линия снова выплевывает это:

malloc.c: 3096: sysmalloc: утверждение `(old_top == (((mbinptr) (((char *) & ((av) -> bins [(1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd))))) && old_size == 0) || (((без знака Long) (Old_Size)> = (Long Unsigned) ((((__ buildin_offsetof (struct malloc_chunk, fd_nextize))+((2 * (sizeof (size_t))) - 1)) & ~ ((2 * (sizeof (size_t))) - 1))) && ((old_top) -> size & 0x1) && (((unsigned long) old_end & pagemask) == 0) 'не удалось. Прерван

Рассматриваемая линия:

int *mult(int size, int *a, int *b) {
    int *out,i, j, *tmp1, *tmp2, *tmp3, *tmpa1, *tmpa2, *tmpb1, *tmpb2,d, *res1, *res2;
    fprintf(stdout, "size: %d\n", size);

    out = (int *)malloc(sizeof(int) * size * 2);
}

Я проверил размер с fprintf, и это положительное целое число (обычно 50 на тот момент). Я пытался позвонить malloc с простым номером, и я все еще получаю ошибку. Я просто озадачен тем, что происходит, и ничто из Google, которое я нашел до сих пор не полезно.

Есть идеи, что происходит? Я пытаюсь выяснить, как собрать более новый GCC на случай, если это ошибка компилятора, но я действительно сомневаюсь в этом.

Это было полезно?

Решение

99,9%, вероятно, что у вас поврежденные память (переосмысленный или недовольство буфера, написал указатель после его освобождения, дважды называемый свободным на одном и том же указателе и т. Д.)

Запустите свой код под Валгринд Чтобы увидеть, где ваша программа сделала что -то неправильное.

Другие советы

Чтобы дать вам лучшее понимание Почему Это происходит, я хотел бы немного расширить ответ @R-Samuel-Klatchko.

Когда вы звоните malloc, То, что действительно происходит, немного сложнее, чем просто дать вам кусок памяти для игры. Под капотом, malloc Также хранит некоторую информацию о домашнем хозяйстве о памяти, которую он дал вам (самое главное, ее размер), так что когда вы звоните free, он знает вещи, например, сколько памяти бесплатно. Эта информация обычно хранится прямо до того, как местоположение памяти возвращается вам malloc. Анкет Можно найти более исчерпывающую информацию в Интернете ™, но (очень) основная идея - это что -то вроде этого:

+------+-------------------------------------------------+
+ size |                  malloc'd memory                +
+------+-------------------------------------------------+
       ^-- location in pointer returned by malloc

Опираясь на это (и очень упрощаю все), когда вы звоните malloc, он должен получить указатель на следующую часть памяти, которая доступна. Один очень простой способ сделать это - взглянуть на предыдущую память, которую он отдал, и двигаться size Байты дальше (или вверх) в памяти. С помощью этой реализации вы получаете свою память, которая выглядит примерно так после распределения p1, p2 а также p3:

+------+----------------+------+--------------------+------+----------+
+ size |                | size |                    | size |          +
+------+----------------+------+--------------------+------+----------+
       ^- p1                   ^- p2                       ^- p3

Итак, что вызывает вашу ошибку?

Что ж, представьте, что ваш код ошибочно записывает в прошлом объем памяти, который вы выделяли (либо потому, что вы выделяли меньше, чем вам нужно, как и ваша проблема, или потому, что вы используете неправильные граничные условия где -то в своем коде). Скажем, ваш код пишет так много данных p2 что он начинает перезаписать то, что в p3S. size поле. Когда вы сейчас следующий звонок malloc, он будет рассмотреть последнее местоположение памяти, которое он вернул, посмотрите на свое поле, перейти к p3 + size а затем начните выделять память оттуда. Поскольку ваш код перезаписан size, Однако это место памяти больше не является после ранее выделенной памяти.

Само собой разумеется, это может разрушить хаос! Реализации malloc Поэтому внесли несколько «утверждений» или проверок, которые пытаются сделать кучу проверки здравомыслия, чтобы поймать это (и другие проблемы), если они собираются произойти. В вашем конкретном случае эти утверждения нарушаются и, таким образом, malloc Прерывает, говоря вам, что ваш код собирается делать то, что он на самом деле не должен делать.

Как указывалось ранее, это грубое упрощение, но достаточно, чтобы проиллюстрировать эту точку зрения. Реализация Glibc malloc составляет более 5 тыс. Линий, и было проведено значительное количество исследований о том, как построить хорошие механизмы распределения динамической памяти, поэтому охватывание всего этого в ответе невозможно. Надеемся, что это дало вам немного взгляда на то, что действительно вызывает проблему!

Мое альтернативное решение использования Valgrind:

Я очень счастлив, потому что я просто помог своему другу отладить программу. У его программы была эта точная проблема (malloc() вызывая прерывание), с тем же сообщением об ошибке от GDB.

Я собрал его программу, используя Адрес дезинфицирующего средства с

gcc -Wall -g3 -fsanitize=address -o new new.c
              ^^^^^^^^^^^^^^^^^^

А потом побежал gdb new. Анкет Когда программа прекращается SIGABRT вызван в последующем malloc(), много полезной информации напечатано:

=================================================================
==407==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6060000000b4 at pc 0x7ffffe49ed1a bp 0x7ffffffedc20 sp 0x7ffffffed3c8
WRITE of size 104 at 0x6060000000b4 thread T0
    #0 0x7ffffe49ed19  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x5ed19)
    #1 0x8001dab in CreatHT2 /home/wsl/Desktop/hash/new.c:59
    #2 0x80031cf in main /home/wsl/Desktop/hash/new.c:209
    #3 0x7ffffe061b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #4 0x8001679 in _start (/mnt/d/Desktop/hash/new+0x1679)

0x6060000000b4 is located 0 bytes to the right of 52-byte region [0x606000000080,0x6060000000b4)
allocated by thread T0 here:
    #0 0x7ffffe51eb50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
    #1 0x8001d56 in CreatHT2 /home/wsl/Desktop/hash/new.c:55
    #2 0x80031cf in main /home/wsl/Desktop/hash/new.c:209
    #3 0x7ffffe061b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

Давайте посмотрим на вывод, особенно трассировку стека:

Первая часть гласит, что есть недействительная операция записи в new.c:59. Анкет Эта линия гласит

memset(len,0,sizeof(int*)*p);
             ^^^^^^^^^^^^

Во второй части говорится, что память, о которой произошло плохая запись, создана в new.c:55. Анкет Эта линия гласит

if(!(len=(int*)malloc(sizeof(int)*p))){
                      ^^^^^^^^^^^

Вот и все. Мне потребовалось всего несколько минут, чтобы найти ошибку, которая запутала моего друга в течение нескольких часов. Ему удалось найти неудачу, но это последующее malloc() Вызовите это, не имея возможности определить эту ошибку в предыдущем коде.

Сумма: попробуйте -fsanitize=address GCC или Clang. Это может быть очень полезно при отладке проблем с памятью.

Вы, вероятно, где -то завышены за пределы выделенного MEM. Тогда базовый SW не поднимает его, пока вы не позвоните Malloc

Там может быть охраняемая ценность, которая поймает Malloc.

Изменить ... добавил это для проверки помощи

http://www.lrde.epita.fr/~akim/ccmp/doc/bounds-comecking.html

Я получил следующее сообщение, похожее на ваше:

    program: malloc.c:2372: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_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)' failed.

Сделал ошибку некоторого метода вызовов ранее, при использовании Malloc. Ошибочно перезаписывая знак умножения '*' с '+', при обновлении фактора после Sizeof ()-оператор при добавлении поля в Unsigned char массив.

Вот код, ответственный за ошибку в моем случае:

    UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)+5);
    b[INTBITS]=(some calculation);
    b[BUFSPC]=(some calculation);
    b[BUFOVR]=(some calculation);
    b[BUFMEM]=(some calculation);
    b[MATCHBITS]=(some calculation);

В другом методе позже я снова использовал Malloc, и он дал сообщение об ошибке, показанное выше. Звонок был (достаточно просто):

    UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)*50);

Подумайте, используя «+»-знак на 1-м вызове, который приводит к неправильному разговору в сочетании с немедленной инициализацией массива после (перезапись памяти, которая не была выделена на массив), вызвала некоторую путаницу с картой памяти Маллока. Поэтому 2 -й звонок пошел не так.

Мы получили эту ошибку, потому что мы забыли умножить на Sizeof (int). Обратите внимание на аргумент в Malloc (..) - это несколько байтов, а не количество машинных слов или чего -то еще.

Я переносил одно приложение из Visual C в GCC через Linux, и у меня была та же проблема с

Malloc.c: 3096: Sysmalloc: утверждение с использованием GCC на Ubuntu 11.

Я перенес тот же код в распределение SUSE (на другом компьютере), и у меня нет проблем.

Я подозреваю, что проблем не в наших программах, а в собственной LIBC.

У меня такая же проблема, я снова использовал Malloc через n в цикле для добавления новых строковых данных Char *. Я столкнулся с той же проблемой, но после выпуска выделенной памяти void free() Проблема была отсортирована

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top