Что такое ошибка glibc free/malloc/realloc invalid next size/invalid pointer и как ее исправить?

вы, скорее всего, увидев этот вопрос, потому что ваш вопрос был закрыт как дубликат этого. Относительно полный список связанных вопросов см. В разделе длинный список возможных дубликатов-выделение памяти c/" class="blnk">C и переполнение границ о переполнении стека Meta.


Пример

С free char*: недопустимый следующий размер (быстро) попросил noobie on 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("%sn", 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

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

1 ответов


ответ, например, вопрос

отдыха дал принята ответ к вопросу примера:

ваш код неверен.

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

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

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

Общий Ответ

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

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

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

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

распространенные причины

  • использовать после освобождения. вы освободили / удалили некоторую память и записываете в нее впоследствии, перезаписывая структуры, необходимые glibc для бухгалтерского учета.
  • Off-by-N ошибка. вы пишете n байт после выделенного куска в нераспределенную память, которую 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);.

что вам нужно сделать сейчас, это засучить рукава и отладить эту проблему

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

инструменты

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

нуждающихся в помощи!--52-->

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

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

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