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

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

  • автор:

Ошибка double free or corruption — fasttop [закрыт]

Вопросы с просьбами помочь с отладкой («почему этот код не работает?») должны включать желаемое поведение, конкретную проблему или ошибку и минимальный код для её воспроизведения прямо в вопросе. Вопросы без явного описания проблемы бесполезны для остальных посетителей. См. Как создать минимальный, самодостаточный и воспроизводимый пример.

Закрыт 2 года назад .

#include #include #include int main() < int n, f, k, max_i; float x, h, a, sum, average, *r; printf("n = "); scanf("%d ", &n); printf("h = "); scanf("%f ", &h); printf("a = "); scanf("%f ", &a); printf("x = "); scanf("%f ", &x); r = (float*)malloc(n * sizeof(float)); //1 f = 0; for (int i = 0; i < n; i++) < r[i] = cos(i*h) - cos(a*x+i*h); if (r[i] < 0 && f == 0) f = i; >for (int i = 0; i < n; i++) printf("Result №1: %f ", r[i]); printf("\n"); //2 int cnt = 0; for (int i = f+1; i < n; i++) < if (r[i] < 0) r[i - cnt] = r[i]; else cnt ++; >k = n - cnt; float *tmp = realloc(r, k * sizeof(float)); r = tmp; for (int i = 0; i < k; i++) printf("Result №2: %f ", r[i]); printf("\n"); //3 max_i = r[0]; for (int i = 0; i < k; i++) if (r[i] >max_i) max_i = i; for (int i = max_i + 1; i < k; i ++) < sum += r[i]; >average = sum / k; printf("Result №3: %f", average); free(tmp); free(r); > 

Отслеживать
задан 17 сен 2021 в 11:21
Anomeanime Anomeanime
1 4 4 бронзовых знака

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Итак, выделили память:

r = (float*)malloc(n * sizeof(float)); 
float *tmp = realloc(r, k * sizeof(float)); 

Т.е. теперь выделенная память по адресу в tmp , r теперь указывает на нечто невалидное (а может быть, на ну же память, что и была) — важно то, что этим указателем больше пользоваться нельзя. И вы совершенно справедливо без всяких проблем переприсваиваете

r = tmp; 

Все верно. Но поясните теперь, зачем вы ДВАЖДЫ освобождаете одну и ту же память?!

free(tmp); free(r); 

О чем, собственно, и получаете сообщение.

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

Есть следующий функции: Функция, сохраняющая текст неизвестного размера в память (Переменная 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 problem

How to solve a double free problem by writing a wrapper function with name free so that i need not change every free call in my source code?

asked Sep 17, 2009 at 14:27
4,144 10 10 gold badges 46 46 silver badges 59 59 bronze badges
Sep 17, 2009 at 15:04
Also relevant: stackoverflow.com/questions/617554/…
Sep 18, 2009 at 9:25
Sorry, blowing my own horn there
Sep 18, 2009 at 9:26

6 Answers 6

No, really. Fix the actual problem. Once free() has been called on a pointer, your code should not be holding on to it for any reason. Null it out so you can’t free it again; this will make any other problems caused by stale pointer dereferencing visible too.

answered Sep 17, 2009 at 14:30
moonshadow moonshadow
88.1k 7 7 gold badges 83 83 silver badges 121 121 bronze badges

+1 for setting the pointer to NULL. That’s actually the easiest solution to never double-free. In any event, writing a custom my_free() that does a free() and then sets the pointer to NULL seems to be the easiest way to ensure this. But that involves code changes 🙂

Sep 17, 2009 at 14:31

Good point about the wrapper functino that takes care of nulling out the pointer. Some Languages even include these and it is always a good practice to use them instead. Delphi objects have a free() method but it is always better to use the FreeAndNil() global function. Of course it also doesn’t throw errors when the pointer is already null which free would.

Sep 17, 2009 at 14:39

@Chris: what makes you think that free(NULL) throws an error? ANSI standard, section 4.10.3.2: «If ptr is a null pointer, no action occurs.»

Sep 17, 2009 at 14:50

«Fix the actual problem» — how do you think he’s going to solve the problem, if you won’t help him write a free replacement that highlights where the double-free occurs?

Sep 17, 2009 at 16:30

If you have two copies of the same pointer, then setting one to null via free() or a wrapper for free() will not prevent an attempt to free the second copy.

Sep 17, 2009 at 18:01

Don’t do that

An easy way is to define your wrapper function and #define free to call your function instead.

#undef free #define free(x) wrapper_free(x) /* . */ int *data = malloc(42); free(data); /* effectively calls wrapper_free(data) */ 

but . don’t do that!

answered Sep 17, 2009 at 14:36
108k 13 13 gold badges 128 128 silver badges 200 200 bronze badges

you should do an #undef free before your defenition: the C standard allows stdlib functions to be aditionally implemented as macros

Sep 17, 2009 at 14:59
@pmg can you explain why not?
Mar 14, 2017 at 13:52

@gewure: free() has a very precise definition. Replacing that with something else is bound to hurt you in the foot in the long run (you will forget about the replacement sooner than you think). Especially true if you give the «redefinition» inside a header file.

Mar 14, 2017 at 17:01

@pmg well. i’ve done it nevertheless (not for the stdlib-free but for some custom-free) — and documented it. Isn’t this rather a question of proper Documentation? e.g. don’t wrap it as «free» but as something like «freeAndNull» — this way it’s pretty clear what is going on.

Mar 20, 2017 at 12:00

The following code intercepts calls to malloc() , realloc() and calloc() for logging.

When calling free() , it checks if the memory was previously allocated with one of these functions. If not, the program will be terminated. Freeing a null pointer will be reported, but execution will continue.

#undef free #define free(PTR) memdebug_free(PTR, #PTR, __FILE__, __func__, __LINE__) #undef malloc #define malloc(SIZE) memdebug_log(malloc(SIZE)) #undef realloc #define realloc(PTR, SIZE) memdebug_log(realloc(PTR, SIZE)) #undef calloc #define calloc(COUNT, SIZE) memdebug_log(calloc(COUNT, SIZE)) #ifndef MEMDEBUG_H #define MEMDEBUG_H extern void memdebug_free(void *ptr, const char *ptr_arg, const char *file, const char *func, int line); extern void *memdebug_log(void *ptr); #endif 
#include #include #include #ifndef MEMDEBUG_TABLE_SIZE // log 16k allocations by default #define MEMDEBUG_TABLE_SIZE 0x4000 #endif static void *alloc_table[MEMDEBUG_TABLE_SIZE]; static size_t top; void *memdebug_log(void *ptr) < assert(top < sizeof alloc_table / sizeof *alloc_table); alloc_table[top++] = ptr; return ptr; >void memdebug_free(void *ptr, const char *ptr_arg, const char *file, const char *func, int line) < if(!ptr) < fprintf(stderr, "%s() in %s, line %i: freeing null pointer `%s` -->continue\n", func, file, line, ptr_arg); return; > for(size_t i = top; i--; ) < if(ptr == alloc_table[i]) < free(ptr); --top; if(i != top) alloc_table[i] = alloc_table[top]; return; >> fprintf(stderr, "%s() in %s, line %i: freeing invalid pointer `%s`-->exit\n", func, file, line, ptr_arg); exit(EXIT_FAILURE); > 

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

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