2010-06-07 2 views
54

Я реализую алгоритм полиномиального разделения и завоевания, поэтому я могу сравнить его с реализацией OpenCL, но я не могу заставить malloc работать. Когда я запускаю программу, она выделяет кучу вещей, проверяет некоторые вещи, а затем отправляет size/2 в алгоритм. Потом, когда я снова попал в malloc линию он выплевывает это:Почему я получаю ошибку утверждения malloc C?

malloc.c: 3096: SysMalloc: Утверждение `(old_top == (((mbinptr) (((символ *) & ((ау) - > 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) -> размер & 0x1) & & ((неподписанных долго) 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, если это ошибка компилятора, но я действительно сомневаюсь в этом.

+0

Я подозреваю, что проблема на самом деле является линией до этого. Возможно, двойная свобода? –

+0

третья строка в программе: INT * мульт (интермедиат размер, Int * а, Int * б) { \t INT * вне, I, J * tmp1, * tmp2, * tmp3, * tmpa1 , * tmpa2, * tmpb1, * tmpb2, d, * res1, * res2; \t fprintf (stdout, "размер:% d \ n", размер); \t \t out = (int *) malloc (размерof (int) * размер * 2); – Chris

ответ

65

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

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

+1

исправлено. Valgrind определенно помог. Я неправильно записал свой старый код matlab и имел цикл for, который повторялся через j, а затем внутри него выполнялся j ++, который больше всего переписывал массив, на котором он писал, и каким-то образом вызвал сбой malloc. спасибо за помощь! – Chris

+0

Valgrind был всего лишь инструментом, который мне нужен, чтобы выяснить, что происходит, когда я получил эту ошибку. Спасибо, что упомянул об этом. – alexwells

+1

Я сделал чистую сборку, и она работала правильно. –

2

Возможно, вы находитесь где-то за пределами выделенного места. тогда базовый sw не поднимает его до тех пор, пока вы не назовете malloc.

Возможно, существует защитное значение, сбитое с помощью malloc.

редактировать ... добавить эту проверку границ помощь

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

1

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

0

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

malloc.c: 3096: SysMalloc: Assertion с помощью GCC на UBUNTU 11.

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

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

40

Чтобы лучше понять , почему это случается, я хотел бы немного расширить ответ на @ r-samuel-klatchko.

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

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

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

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

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

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

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

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

+0

Это должен быть принятый ответ .. –

1

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

 

    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. 

Ошибся некоторый вызов метода перед тем, при использовании таНоса. Неожиданно переписывал знак умножения '*' с символом '+' при обновлении коэффициента после оператора sizeof() при добавлении поля в unsigned char array.

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

 

    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); 

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

 

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

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

0

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