2010-12-16 3 views
3

gcc 4.5.1 c89Невозможно освободить память после использования strdup

Я пытаюсь освободить память. Однако, когда я проверяю valgrind, память не была освобождена. Мне интересно, что я делаю неправильно.

I имеет следующую структуру:

typedef struct tag_cand_results { 
    char *candidate_winners[NUMBER_OF_CANDIDATES]; 
} cand_results; 

я создаю объект этой структуры:

cand_results *results = NULL; 

я выделить память для структуры.

results = calloc(1, sizeof *results); 

Назначают некоторые данные к нему

results->candidate_winners[0] = strdup("Steve Martin"); 
results->candidate_winners[1] = strdup("Jack Jones"); 

Тогда я пытаюсь освободить всех памяти, выделяемой:

free(results->candidate_winners[0]); 
free(results->candidate_winners[1]); 
free(results); 

Just to be safe assign to NULL 
results = NULL; 

я получаю следующий выход из Valgrind.

==8119== 72 bytes in 6 blocks are definitely lost in loss record 1 of 2 
==8119== at 0x4A05E46: malloc (vg_replace_malloc.c:195) 
==8119== by 0x3FE2E82A91: strdup (strdup.c:43) 
==8119== by 0x400E5A: main (driver.c:116) 
==8119== 
==8119== 72 bytes in 6 blocks are definitely lost in loss record 2 of 2 
==8119== at 0x4A05E46: malloc (vg_replace_malloc.c:195) 
==8119== by 0x3FE2E82A91: strdup (strdup.c:43) 
==8119== by 0x400E72: main (driver.c:117) 

Я не знаю, почему память не была освобождена?

Большое спасибо за любые предложения,

+0

Вы можете разместить наименьшее * полная * Программа, о которой Valgrind еще жалуется таким образом. – NPE

+0

Что-то происходит в другом месте моего исходного кода. Просто отправил комментарий в Pax ниже. – ant2009

ответ

4

Если это на самом деле последовательность событий, то Valgrind неправильно. Память : освобождается.


Как лучшая техника, запрошенная в своем комментарии, как правило, я бы сказал, Valgrind, но, возможно, не в этом случае :-)

Некоторых вещей, чтобы проверить.

  • Что произойдет, если вы просто позвоните malloc(30) вместо strdup(some_string) (в обоих случаях)?
  • Снимите (malloc-or-strdup)/free pairs по одному, чтобы узнать, что произойдет.
  • Я не видел ваш фактический код, поэтому поставлю printf до и после каждой строки strdup и free, чтобы убедиться, что все они запущены.
  • Отправьте здесь небольшую небольшую программу (у которой есть проблема), чтобы мы могли ее проверить.

Для чего это стоит, следующий маленький (в комплекте) Программа:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define NUMBER_OF_CANDIDATES 10 
typedef struct tag_cand_results { 
    char *candidate_winners[NUMBER_OF_CANDIDATES]; 
} cand_results; 

int main (void) { 
    cand_results *results = NULL; 

    results = calloc(1, sizeof *results); 

    results->candidate_winners[0] = strdup("Steve Martin"); 
    results->candidate_winners[1] = strdup("Jack Jones"); 

    free(results->candidate_winners[0]); 
    free(results->candidate_winners[1]); 
    free(results); 

    results = NULL; 

    return 0; 
} 

приводит следующий вывод VALGRIND:

==9649== Memcheck, a memory error detector 
==9649== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. 
==9649== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for 
     copyright info 
==9649== Command: ./qq 
==9649== 
==9649== 
==9649== HEAP SUMMARY: 
==9649==  in use at exit: 0 bytes in 0 blocks 
==9649== total heap usage: 3 allocs, 3 frees, 64 bytes allocated 
==9649== 
==9649== All heap blocks were freed -- no leaks are possible 
==9649== 
==9649== For counts of detected and suppressed errors, rerun with: -v 
==9649== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 8) 

Другими словами, никаких проблем. Это может быть что-то еще в вашем случае (возможно, проблема с окружающей средой). Этот конкретный запуск выполнялся на Ubuntu Lucid (10.04), gcc 4.4.3, режим c89.

Я бы предложил ввести код именно в вашей системе, чтобы узнать, что произойдет. В командной строке я использовал для компиляции и тестирования был:

gcc -std=c89 -o qq qq.c 
valgrind ./qq 
+0

Я просто переключу свой проект на другую ветку. Я достал весь несвязанный код и только исходный код, где я фактически выделяю память. Таким образом, код выглядит так, как я опубликовал. Память была освобождена. Поэтому я думаю, что что-то происходит в другом месте. Мне нужно будет продолжить расследование. Однако, какова наилучшая техника для поиска ошибок памяти? – ant2009

+0

Спасибо за информацию. Я проверю свой исходный код и отчитаюсь с любой новой информацией. Благодарю. – ant2009

1

«72 байта в 6 блоков», не звучит как «Стив Мартин» или «Jack Jones». Вы не переписываете указатели в какой-то момент (!)?

2

В ваших распределениях/освобождениях нет очевидной ошибки.

Похоже, что содержимое результата было каким-то образом изменено (перезаписано каким-то диким указателем?).

Один простой способ проверить, что должно указывать значения адреса памяти указателя (с помощью printf («% p», ...)) сразу после выделения с использованием strdup и непосредственно перед освобождением. Если это изменилось: бинго!

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

Теперь, если указатель действительно изменил, как точно определить, где это происходит?

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

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

Теперь в потоке управления поставил утверждения, как:

утверждают (результат == saved_result);

В каком-то месте утверждение должно потерпеть неудачу, и вы в конечном итоге найдете проблему.

Вернитесь, не забудьте удалить свои утверждения, которые не должны быть оставлены в конечном проекте. Чтобы убедиться в этом, просто удалите переменную saved_result. Программа не будет компилироваться в режиме отладки, если оставлено какое-либо утверждение.

2

Вы также можете отладить приложение с помощью gdb и посмотреть, будет ли изменен какой-либо указатель с помощью команды «смотреть». Поместите точку останова на основную функцию и выполните шаг за шагом, чтобы узнать, где находится проблема.

С уважением,

Miguel