使用strdup后无法释放内存

发布于 2024-10-07 15:00:11 字数 1294 浏览 6 评论 0原文

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)

不知道为什么内存没有被释放?

非常感谢您的任何建议,

gcc 4.5.1 c89

I am trying to free some memory. However, when I check with valgrind the memory hasn't been freed. I am wondering what I am doing wrong.

I have the following structure:

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

I create an object of this structure:

cand_results *results = NULL;

I allocate some memory for the structure.

results = calloc(1, sizeof *results);

Assign some data to it

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

Then I try to free all the memory allocated:

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

Just to be safe assign to NULL
results = NULL;

I get the following output from 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)

I don't know why the memory is not been freed?

Many thanks for any suggestions,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

热鲨 2024-10-14 15:00:11

如果这实际上是事件的顺序,那么 valgrind 就是错误的。内存正在被释放。


至于您评论中要求的最佳技术,通常我会说 valgrind 但在这种情况下可能不会:-)

有些事情需要检查。

  • 如果您只调用 malloc(30) 而不是 strdup(some_string) (在这两种情况下)会发生什么?
  • 一次删除一个(malloc-or-strdup)/free 对,看看会发生什么。
  • 我还没有看到您的实际代码,因此在每个 strdupfree 行之前和之后放置一个 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

If that is actually the sequence of events, then valgrind is wrong. The memory is being freed.


As to the best technique requested in your comment, normally I would say valgrind but perhaps not in this case :-)

Some things to check.

  • What happens if you just call malloc(30) instead of strdup(some_string) (in both cases)?
  • Remove the (malloc-or-strdup)/free pairs one at a time to see what happens.
  • I haven't seen your actual code so put a printf before and after every strdup and free line to make sure they're all being run.
  • Post a full small program here (that exhibits the problem) so we can check it out.

For what it's worth, the following small (complete) program:

#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;
}

results in the following valgrind output:

==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)

In other words, no problems. So it may be something else in your case (an environment issue perhaps). This particular run was done on Ubuntu Lucid (10.04), gcc 4.4.3, c89 mode.

I'd suggest typing in that code exactly on your system to see what happens. The command line I used to compile and test was:

gcc -std=c89 -o qq qq.c
valgrind ./qq
沉鱼一梦 2024-10-14 15:00:11

您还可以使用 gdb 调试应用程序,并使用“watch”命令观察是否有任何指针发生更改。在你的main函数上设置一个断点,然后一步步跟进,找出问题所在。

问候,

米格尔

You can also debug your application with gdb and watch if any pointer gets changed with the "watch" command. Place a breakpoint on your main function and do a step by step followup to discover where the problem resides.

Regards,

Miguel

天生の放荡 2024-10-14 15:00:11

您的分配/释放没有明显的错误。

看起来结果的内容已经以某种方式改变了(被一些野指针覆盖?)。

一种简单的检查方法是在使用 strdup 分配之后和释放之前立即打印指针的内存地址值(使用 printf("%p", ...))。如果它改变了:宾果游戏!

对结果也执行此操作,另一种解释可能是指向结果的指针已更改(以及今后指向的值)。

现在,如果指针确实发生了变化,如何确定它发生的位置?

一种解决方案是使用调试器运行程序。在某些情况下这可能非常耗时,但通常是有效的。但如果这不是一个选择,还有另一种方法。我通常发现它比使用调试器更快。

将分配的指针的副本保留在另一个变量中,最好使其远离损坏的指针所在的内存块(通常使用全局变量)。

现在在控制流中放置如下断言:

assert(result == saving_result);

在某些地方断言应该失败,你最终会发现问题。

之后,您不应该忘记删除不应留在最终项目中的断言。为了确保这一点,只需删除saved_result变量即可。如果留下任何断言,程序将不会在调试模式下编译。

There is no obvious error in your allocations/frees.

It looks like the content of result has been changed somehow (overwritten by some wild pointer ?).

One easy way to check that is to print memory address values of pointer (using printf("%p", ...)) immediately after the allocation using strdup and just before freeing. If it changed : bingo!

Do it also with result, another explanation could be that the pointer to result has changed (and henceforth the values pointed to).

Now, if the pointer has indeed changed how to pinpoint where it occurs ?

One solution can be to run the program using a debugger. This can be very time consuming in some case, but it usually works. But if this is not an option, there is another way. I usually find it faster than using a debugger.

Keep a copy of the allocated pointer in another variable, preferably make it remote from the memory chunk where is your corrupted pointer (a global will usually do).

Now in the control flow put assertions like:

assert(result == saved_result);

At some place the assertion should fail and you will eventually find the problem.

Aftwerward, you should not forget to remove your assertions that should not be left in the final project. To be sure of that just remove the saved_result variable. The program won't compile in debug mode if any assertion is left.

顾铮苏瑾 2024-10-14 15:00:11

“6 个块中的 72 个字节”听起来不像“史蒂夫·马丁”或“杰克·琼斯”。您不会在某个时刻覆盖指针(!)?

"72 bytes in 6 blocks", doesn't sound like "Steve Martin" or "Jack Jones". You're not overwriting the pointers at some point(!)?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文