【问题标题】:It seems stack-based variable not be released after function at C似乎基于堆栈的变量在 C 函数后没有被释放
【发布时间】:2019-04-15 22:43:23
【问题描述】:

我是C新手。众所周知,堆栈内存中的变量在函数结束后会被释放。但是在我的测试中,它并没有被释放,内存占用。

例子很清楚:

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

void run() {
    printf("Start test. Memory usage in task manager: 504KB \n");
    sleep(5);

    char buf1[3145728];
    memset(buf1, 'x', 3145728);
    printf("buf1 Present. Memory usage in task manager: 3.9MB \n");

    sleep(10);
    return;
}

int main() {
    run();

    printf("run() ends. But memory usage in task manager is still: 3.9MB \n");
    sleep(10);

    char buf2[3145728];
    memset(buf2, 'y', 3145728);
    printf("buf2 Present. Memory usage in task manager: 7.0MB \n");

    sleep(15);
    return 0;
}

我认为,run() 函数之后的内存使用应该回到最初的状态,但似乎变量没有被释放并留在内存中。

我错了吗?

更多详情:

  • 写sleep是为了有时间看看任务管理器。
  • 我用过gcc编译器。

【问题讨论】:

  • 您正在对标准无法保证的事物做出假设。除了sleep() 和printf() 之外的所有定义和语句都可以优化掉,因为它们不参与程序的可观察行为。
  • sleep 在这里不起作用,编译器在此之前分配自动内存。也许如果它是一个可变长度数组......
  • 写sleep是为了有时间看看任务管理器。正因为如此:-)
  • 你是如何检查内存是否被释放的?你的平台是什么?
  • 也许操作系统正在为您正在使用的大堆栈进行写入时复制分配。并且这个内存没有被释放,所以你可以一遍又一遍地调用 run() 而不会重新分配。

标签: c memory memory-management memory-leaks


【解决方案1】:

首先不要太相信任务管理器。这不是很准确。

另一件事是编译器有一个你并不完全了解的分配策略。

众所周知,栈内存中的变量会在函数结束后释放。

“著名”是您不应该在局部变量上创建引用并存储/返回它,因为它有可能被超出范围使用。

如果您在该函数上循环,或创建另一个占用大致相同数量(或更少)堆栈的函数,然后立即调用它,您会注意到内存确实没有增加.

这是因为编译器运行时不会自动调整堆栈大小。它只是保持它为下一次分配(这是堆栈 size 和 容量 之间的差异)。没有“内存泄漏”。您甚至可以配置可执行文件(在链接阶段,以及在 Windows 上使用 EDITBIN 等工具)以在启动时预分配所有堆栈,以避免调整大小和内存移动。

【讨论】:

  • 谢谢。为什么在示例中的 main() 操作中,紧随其后的是 run() 函数,增加内存,但 run() 之后的函数没有?
  • 不要认为 C 会像您正在阅读它们那样解释指令或声明。例如,并不是因为您在程序中间声明了数组,它才会在 睡眠后分配。您可以确定编译器内存方面没有错误,或者没有人可以使用它。你的情况不是名义上的情况。我建议你在循环中调用run,你不会看到堆栈增加。
  • 谢谢。我已经测试了循环,你是对的。但我的问题是:你说过or create another function that eats roughly the same amount of stack (or less) and you call it right afterwards, you'll notice that the memory does not increase. 我已经创建了那个函数,我不会看到堆栈增加,正如你所说的。但是为什么当我在 main() 中创建缓冲区时它会增加堆栈,而当我在 run() 之外的其他函数中创建缓冲区时,堆栈不会增加?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-02
  • 1970-01-01
  • 2021-09-27
  • 1970-01-01
  • 2020-04-07
  • 1970-01-01
相关资源
最近更新 更多