Как решить ошибку double free
Перейти к содержимому

Как решить ошибку double free

  • автор:

Ошибка 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

Screenshot of debugger displaying double-free error in example 1.

Пример «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

Screenshot of debugger displaying double-free error in example 2.

Пример: 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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *