Что такое ошибка glibc free / malloc / realloc недопустимая ошибка следующего размера / недопустимого указателя и как ее исправить?

Вы, скорее всего, видите этот вопрос, потому что ваш вопрос был закрыт как дубликат этого. Для умеренно полного списка связанных вопросов, пожалуйста, см . Длинный список возможных дубликатов – ограничения на выделение и превышение памяти C в Meta Stack Overflow.


Пример

Из бесплатного char *: недопустимый следующий размер (быстрый), заданный noobie в 2014-04-11.

Я освобождаю char* после процесса конкатенации, но получаю эту ошибку:

 free(): invalid next size (fast): 0x0000000001b86170 

Это мой код:

 void concat(stringList *list) { char *res = (char*)malloc(sizeof(char*)); strcpy(res, list->head->string); list->tmp = list->head->next; while (list->tmp != NULL) { strcat(res, ","); strcat(res, list->tmp->string); list->tmp = list->tmp->next; } printf("%s\n", res); free(res); } 

Общий вопрос

При запуске моей программы я вижу следующее сообщение об ошибке:

 *** glibc detected *** ./a.out: free(): corrupted unsorted chunks: 0x12345678 *** 

После *** glibc detected *** и имени программы подробная информация может содержать любое из следующих действий, за которым следует шестнадцатеричный адрес (отображается как 0x12345678) и еще один *** :

  • free(): corrupted unsorted chunks: 0x12345678
  • free(): invalid next size (fast): 0x12345678
  • free(): invalid next size (normal): 0x12345678
  • free(): invalid pointer: 0x12345678
  • free(): invalid size: 0x12345678
  • malloc(): corrupted unsorted chunks: 0x12345678
  • malloc(): corrupted unsorted chunks 2: 0x12345678
  • malloc(): memory corruption: 0x12345678
  • malloc(): memory corruption (fast): 0x12345678
  • malloc(): smallbin double linked list corrupted: 0x12345678
  • munmap_chunk(): invalid pointer: 0x12345678
  • realloc(): invalid next size (fast): 0x12345678
  • realloc(): invalid old size (fast): 0x12345678
  • realloc(): invalid pointer: 0x12345678
  • corrupted double-linked list: 0x12345678

Это происходит при вызове функции frobnicate() ; что не так с этой функцией?

Ответ для примера

unind дал принятый ответ на примерный вопрос:

Ваш код неправильный.

Вы выделяете пространство для одного указателя ( malloc(sizeof(char*)) ), но без символов. Вы переписываете выделенное пространство со всеми строками, вызывая неопределенное поведение (в данном конкретном случае, развращая данные бухгалтерского учета malloc() ).

Вам не нужно выделять пространство для указателя ( res ); это локальная переменная. Вы должны выделить место для всех символов, которые вы хотите сохранить по адресу, удерживаемому указателем.

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

Общий ответ

То, что вы видите, является результатом коррупции во внутренних структурах распределителя glibc. Когда вы назначаете или освобождаете динамическую память, распределитель должен управлять памятью, зарезервированной ею из ОС, и, в зависимости от запрошенного вами действия, найдите новый кусок для раздачи, сортируйте освобожденный кусок в список тех, которые он может передать позже или вернуть память операционной системе. Эти сообщения об ошибках показывают, что структуры данных, которые он использует для управления этой функциональностью, повреждены.

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

Да, это означает, что ошибка может быть в любой вашей программе или сторонних библиотеках, которые вы используете .

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

Общие причины

  • Используйте после бесплатного. После этого вы освободили / удалили некоторую память и записали ее, перезаписав структуры glibc, необходимые для ведения бухгалтерии.
  • Ошибка Off-by-N. Вы пишете N байтов после выделенного fragmentа в нераспределенную память, которую glibc использует внутри своей учетной записи.
  • Неинициализированные указатели. Вы не инициализируете указатель. По совпадению это указывает на некоторую память, зарезервированную glibc, но не выделенную вашей программой, и вы пишете ей.
  • Выделение неправильного пространства. Это может быть связано с тем, что вы написали long *data = malloc(number * 4) вместо long *data = malloc(number * sizeof(long)); или (лучше) long *data = malloc(number * sizeof(*data)); , Есть много других способов ошибочного вычисления размера. Другой распространенный – забыть учитывать символ нулевого терминатора в конце строки: char *copy = malloc(strlen(str)); вместо char *copy = malloc(strlen(str)+1); ,

Теперь вам нужно свернуть armва и отладить эту проблему

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

инструменты

  • valgrind Инструмент, созданный в основном для поиска именно таких ошибок. Если он не может найти что-либо, убедитесь, что вы используете последнюю версию, и вы также пытаетесь использовать exp-sgcheck инструмент exp-sgcheck . Если вы используете многопоточный код, причина может также быть связана с условием гонки, поэтому вы можете попробовать включить включенные шашки состояния гонки drd и helgrind для более глубокого понимания. На момент написания этой статьи valgrind поддерживает следующие платформы:
    • X86 / Linux,
    • AMD64 / Linux,
    • ARM / Linux,
    • Ppc32 / Linux,
    • PPC64 / Linux,
    • S390x / Linux,
    • MIPS32 / Linux,
    • MIPS64 / Linux,
    • ARM / Android (2.3.x и более поздние версии),
    • X86 / Android (4.0 и более поздние версии),
    • X86 / Дарвин и
    • AMD64 / Darwin (Mac OS X 10.7 с ограниченной поддержкой 10.8).
  • purify Подобный инструмент для valgrind, но коммерческий и нацеленный на другой набор платформ.
  • AddressSanitizer Аналогичный инструмент, но интегрированный в toolchain компилятора (gcc и clang).
  • efence Падение замены распределителя, которое попытается сбой вашей программы раньше, так что вы можете узнать с обычным отладчиком, где произошла запись в недопустимую память.
  • dmalloc – библиотека с аналогичной целью.

Необходима дополнительная помощь

Если вы не можете решить свою проблему с помощью одного из этих инструментов, вы должны попытаться создать MCVE ( как создать минимальный, полный и проверенный пример? ) Или, что то же самое, SSCCE ( Short, Self Contained, Correct (Compilable) , Пример ).

Не забудьте работать с копией вашего кода, потому что для создания MCVE вам необходимо безжалостно удалить код, который не поможет воспроизвести проблему. Использование VCS (системы контроля версий) для оказания помощи – хорошая идея; вы можете записывать промежуточные этапы, чтобы свести проблему к минимуму. Это может быть новый резервный repository, который просто уменьшит вашу проблему до управляемого размера.

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

  • что использует MemoryFile в android
  • Есть ли способ получить ссылочный адрес?
  • Явное освобождение памяти в c #
  • AngularJS - $ destroy удаляет прослушиватели событий?
  • В Java, каков наилучший способ определить размер объекта?
  • Память стека против памяти кучи
  • Заказ локального распределения переменных в стеке
  • «Ошибка при отсутствии памяти (Java)» при использовании пакетов R и XLConnect
  • Как его срок службы возвращаемого значения распространяется на область действия вызывающей функции, когда она привязана к константной ссылке в вызывающей функции?
  • OpenCV для использования в буферах памяти или указателях файлов
  • Возврат локальных данных из функций в C и C ++ с помощью указателя
  • Давайте будем гением компьютера.