gcc 4.5.1 c89
我想释放一些记忆。但是,当我用valgrind检查时,内存尚未被释放。我想知道我做错了什么。
我有以下结构:
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 :(得分:4)
如果那是实际事件序列,则valgrind是错误的。内存 被释放。
关于评论中要求的最佳技术,通常我会说valgrind,但在这种情况下可能不会: - )
要检查的一些事情。
malloc(30)
而非strdup(some_string)
(在这两种情况下),会怎样?(malloc-or-strdup)/free pairs
一个,看看会发生什么。strdup
和free
行之前和之后放置printf,以确保它们全部正在运行。对于它的价值,以下小(完整)程序:
#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
答案 1 :(得分:2)
您的分配/免费中没有明显错误。
看起来结果的内容已经被某种方式改变了(被一些狂野的指针覆盖了?)。
一种简单的检查方法是在使用strdup分配之后立即打印指针的内存地址值(使用printf(“%p”,...))。如果它改变了:宾果!
也可以使用结果,另一种解释可能是指向结果的指针已经改变(以及之后指向的值)。
现在,如果指针确实改变了如何确定它发生的位置?
一种解决方案是使用调试器运行程序。在某些情况下,这可能非常耗时,但它通常有效。但如果这不是一种选择,还有另一种方式。我通常发现它比使用调试器更快。
将分配的指针的副本保存在另一个变量中,最好使其远离内存块,这是您的损坏指针(全局通常会这样做)。
现在在控制流程中输入断言如:
断言(结果== saved_result);
在某个地方,断言应该失败,你最终会发现问题。
Aftwerward,您不应忘记删除不应留在最终项目中的断言。为了确保这一点,只需删除saved_result变量即可。如果有任何断言,程序将无法在调试模式下编译。
答案 2 :(得分:2)
您还可以使用gdb调试应用程序,并使用“watch”命令监视是否有任何指针被更改。在主函数上放置一个断点,然后逐步跟进以发现问题所在的位置。
此致
米格尔
答案 3 :(得分:1)
“6个街区中的72个字节”,听起来不像“史蒂夫马丁”或“杰克琼斯”。你不是在某个时候覆盖指针(!)?