Ошибка double free or corruption
Есть следующий функции: Функция, сохраняющая текст неизвестного размера в память (Переменная sentence отвечает за количество предложений):
char** text_input(char **text, int *sentence) < int slen = 50; char ch; int symb = 0; while (ch != '\n')< text[*sentence] = (char*)malloc(slen * sizeof(char)); while (ch != '.' && ch != '\n')< ch = getchar(); if (ch == '\n')< break; >if (symb >= slen - 1) < slen += 50; text[*sentence] = (char*)realloc(text[*sentence], slen * sizeof(char)); >text[*sentence][symb++] = ch; > if (ch == '\n') < break; >ch = '\0'; text[*sentence][symb] = ch; *sentence += 1; text = (char**)realloc(text, (*sentence + 1) * sizeof(char*)); symb = 0; slen = 50; > return text; >
И функция, удаляющая из текста одинаковые предложения:
char** text_redaction(char **text, int *sentence) < int count = 0; for(int sentence1 = 0; sentence1 < *sentence - 1; sentence1++)< for (int sentence2 = sentence1 + 1; sentence2 < *sentence; sentence2++)< if (strlen(text[sentence1]) == strlen(text[sentence2]))< for(int j = 0; j < strlen(text[sentence1]); j++)< if (toupper(text[sentence1][j]) == toupper(text[sentence2][j]))< ++count; >> if (count == strlen(text[sentence1])) < free(text[sentence2]); for (int l = sentence2; l < *sentence; l++)< text[l] = text[l+1]; >text[*sentence - 1] = NULL; sentence2 -= 1; *sentence -= 1; count = 0; > > > > return text; >
При запуске вторая выдает ошибку: double free or corruption Где ошибка?
Отслеживать
задан 9 дек 2018 в 21:17
23 4 4 бронзовых знака
«При запуске» чего? Как выглядит вызывающий код?
9 дек 2018 в 21:53
Реалок странный)
9 дек 2018 в 22:09
В каком месте «double free or corruption»? В какой строке? На каком входе? Почему эта информация отсутствует в тексте вопроса?
Ошибка: double-free
В C можно free вызвать ошибочно. В C++можно вызывать delete несколько раз. В этих примерах отображаются ошибки с delete , free а также HeapCreate .
Пример C++ — double operator delete
// example1.cpp // double-free error int main() < int *x = new int[42]; delete [] x; // . some complex body of code delete [] x; return 0; >
Чтобы создать и проверить этот пример, выполните следующие команды в командной строке разработчика Visual Studio 2019 версии 16.9 или более поздней:
cl example1.cpp /fsanitize=address /Zi devenv /debugexe example1.exe
Результирующая ошибка — double operator delete

Пример «C» — double free
// example2.cpp // double-free error #include #include int main(int argc, char** argv) < char* x = (char*)malloc(10 * sizeof(char)); memset(x, 0, 10); int res = x[argc]; free(x); // . some complex body of code free(x + argc - 1); // Boom! return res; >
Чтобы создать и проверить этот пример, выполните следующие команды в командной строке разработчика Visual Studio 2019 версии 16.9 или более поздней:
cl example2.cpp /fsanitize=address /Zi devenv /debugexe example2.exe
Результирующая ошибка — double free

Пример: Windows HeapCreate double HeapFree
// example3.cpp // double-free error #include #include int main()
Чтобы создать и проверить этот пример, выполните следующие команды в командной строке разработчика Visual Studio 2019 версии 16.9 или более поздней:
cl example3.cpp /fsanitize=address /Zi devenv /debugexe example3.exe
double free or corruption (out)
Есть класс Matrix , в конструкторе память динамически резервируется, в деструкторе — освобождается, но при попытке освободить память деструктор терпит фиаско с сообщением double free or corruption (out) . Это происходит если cols>rows , т.е при Matrix(3, 3) исключения нет, а вот при Matrix(3, 4) есть.
struct Matrix < double **a; unsigned rows, cols; Matrix(const unsigned rows, const unsigned cols): rows(rows), cols(cols) < a = new double*[rows]; for (unsigned i = 0; i < cols; ++i) < a[i] = new double[cols]; >> ~Matrix() < for (unsigned i = 0; i < rows; ++i) < delete []a[i]; // double free or corruption (out) >delete []a; > >; int main()
Пробовал использовать malloc/calloc/free — та же ошибка.

neversleep ★★
21.01.18 10:26:17 MSK
Поиск ошибок работы с памятью при помощи Electric Fence
Electric Fence — библиотека предназначенная для поиска ошибок работы с памятью в программах, использующих стандартные функции библиотеки языка C — malloc , calloc , realloc и т.п. Данная библиотека написана Bruce Perens в 1990-х годах и является широко известным средством для поиска ошибок, хотя в последние годы у нее появились очень мощные конкуренты в лице Valgrind и Google Performace Tools.
С помощью Electric Fence вы можете производить поиск двух типов ошибок:
- доступ к уже освобожденной памяти
- доступ к памяти за границами выделенных блоков
Для выполнения этих задач Electric Fence использует механизмы защиты участков виртуальной памяти, предоставляемых операционной системой 1 — для ее работы требуется наличие функций mprotect & mmap.
Работа с библиотекой
Использование библиотеки достаточно просто — необходимо слинковать вашу программу с библиотекой efence 2 или загрузить ее с помощью LD_PRELOAD , например:
# ulimit -c unlimited # LD_PRELOAD=/usr/lib/libefence.so.0.0 ./your_program
Первая строка необходима для того, чтобы разрешить генерацию посмертного дампа состояния программы, что по умолчанию запрещено на большинстве систем.
Если код пытается получить доступ к памяти за пределами выделенного блока, или осуществить доступ к освобожденному блоку памяти, то это приводит к возникновению аппаратной ошибки и аварийному завершению программы (segmentation fault). После этого вы можете использовать отладчик для того, чтобы посмотреть стек вызова функций приведший к возникновению ошибки. Например, рассмотрим выполнение следующей программы, содержащую двойное освобождение памяти:
#include int main(int argc, char** argv) < char* mem=(char*)(malloc(10)); free(mem); free(mem); return 0; >
Скомпилируем программу с отладочной информацией и запустим ее под управлением Electric Fence:
# LD_PRELOAD=/usr/lib/libefence.so.0.0 ./test-double-free Electric Fence 2.1 Copyright (C) 1987-1998 Bruce Perens. ElectricFence Aborting: free(b7d31ff4): address not from malloc(). [1] 5928 illegal hardware instruction (core dumped) LD_PRELOAD=/usr/lib/libefence.so.0.0 ./test-double-free
После завершения программы в текущем каталоге вы найдете файл core , который и содержит посмертный дамп состояния программы. С помощью отладчика заглянем в полученный дамп чтобы найти место, в котором возникла ошибка:
# gdb ./test-double-free core . . пропущенные строки с сообщениями о загрузке библиотек . Core was generated by `./test-double-free'. Program terminated with signal 4, Illegal instruction. #0 0xb7eea410 in __kernel_vsyscall () (gdb) bt #0 0xb7eea410 in __kernel_vsyscall () #1 0xb7da2366 in kill () from /lib/tls/i686/cmov/libc.so.6 #2 0xb7ee5c54 in EF_Abort () from /usr/lib/libefence.so.0.0 #3 0xb7ee50a2 in free () from /usr/lib/libefence.so.0.0 #4 0x080483da in main () at test-double-free.c:6
С помощью команды bt отладчика gdb мы получаем стек вызова функций, который нам показывает, что ошибка возникла в строке 6 файла с исходным текстом test-double-free.c . Остается исправить эту ошибку и снова запустить программу на выполнение.
Управление поведением библиотеки
В большинстве случаев для использования библиотеки достаточно стандартных настроек. Но если необходимо, то пользователь может изменить поведение библиотеки с помощью определенных переменных среды:
EF_PROTECT_BELOW При значении этой переменной равном 1 включается режим проверки доступа к областям памяти, которые находятся до выделенного блока (по умолчанию проверяется доступ к памяти за верхней границей выделенного блока) EF_PROTECT_FREE При ненулевом значении, Electric Fence прекращает возвращать освобождаемую память в пул свободной памяти, откуда она снова может быть выделена программе. Стоит отметить, что при работе в данном режиме, программе может понадобиться значительно большее количество свободной памяти. EF_ALLOW_MALLOC_0 При ненулевом значении этой переменной, Electric Fence разрешает выделение блоков памяти с длиной 0, что по умолчанию приводит к возникновению ошибки. EF_ALIGNMENT Устанавливает значение, которое будет использоваться для выравнивания границ выделяемых блоков памяти. По умолчанию это значение равно sizeof(int) . Установка нестандартных значений может быть полезна для обнаружения некоторых видов ошибок, но перед тем как это делать прочитайте раздел «Word-alignment and Overrun Detection» в справочной странице libefence.3 , входящей в состав пакета. EF_FILL позволяет указать число от 0 до 255, которое будет использоваться как заполнитель для выделяемых областей памяти
Использование EF_PROTECT_BELOW очень полезно для проверки того, не происходит ли доступ к областям памяти, которые находятся до выделенного блока. Обычно проверка программы происходит следующим образом — сначала исправляются все ошибки, возникающие при использовании стандартных настроек, а затем, включается режим EF_PROTECT_BELOW и все проверки выполняются снова.
1. Работа библиотеки была протестирована на Linux, Solaris, AIX, HP-UX и еще некоторых операционных системах. В принципе, библиотека должна работать на всех POSIX-совместимых системах, реализующих функции mmap & mprotect.
2. Нельзя использовать Electric Fence вместе с другими библиотеками, которые предназначены для поиска ошибок работы с памятью.
Last change: 05.03.2013 16:54