堆vs堆栈与bss部分

时间:2012-10-25 06:53:01

标签: c memory

使用常量预定义大小(如缓冲区)存储运行时数据的最佳位置:堆(malloc),堆栈(例如函数内的char buf[BUFSIZE])或bss部分(全局区域中的char buf[BUFSIZE] )?

4 个答案:

答案 0 :(得分:5)

这取决于你想用缓冲区做什么。

通常应该避免全球化,你必须非常小心,不要忽视随之而来的问题。

如果仅在一个函数中需要缓冲区且BUFSIZE不是太大(最多几KB),则可以将其设置为本地。但是,随着嵌套调用的加起来,请密切关注总堆栈使用情况。只有在想要在调用之间保持值时才需要静态本地,从而有效地使其成为具有本地范围的全局。但是当你进行多线程或想要使用递归时,它会给你带来麻烦。

如果缓冲区用于函数调用或BUFSIZE非常大,则使用malloc()/ free()。如果经常调用该函数,最好在函数外部分配一次,执行所有函数调用,然后释放它,而不是为每个函数调用分配和释放另一个缓冲区。但这接近于过早优化,因为它不必要地将函数的内部结构与外部调用者耦合。

从更大的角度来看,当你的程序增长时,你想给它更多的结构并清楚地定义责任,尤其是。对于内存处理,否则你最终会失去跟踪。此缓冲区是具有特定任务的特定模块的工作详细信息。一种典型的方法是使用结构以OOP方式组织数据,使用create和destroy函数来分配和释放这样的对象。然后缓冲区可以成为此结构的一部分。

struct s_foo
{
    char buf[BUFSIZE];
    ...
};

struct s_foo *foo_create (...);
void foo_destroy (struct s_foo *foo);
void foo_action (struct s_foo *foo);

这允许您并行拥有任意数量的foos,每个foos都有自己的缓冲区,彼此独立。此外,缓冲区内容保持在调用之间,没有静态变量的麻烦。

答案 1 :(得分:1)

在这种情况下,如果函数之间没有共享缓冲区,IMO最好的选项是本地静态变量:

void func(...) {
    static char buf[BUFSIZE];
}

这可以避免重复分配/释放和命名空间混乱。

修改

此解决方案不是线程安全的,但全局变量也不是。

答案 2 :(得分:0)

您需要一个在加载时分配的静态变量,并保留在程序的整个生命周期中。所以选项三,即所谓的“bss”部分。

答案 3 :(得分:0)

显然,堆已经出局,因为大小有限。我不会去寻求静力学,因为它们不是可重入的,它们会在递归中带来严重破坏。所以,把它放在堆栈框架中。

void f(...) {
    char buf[BUFSIZE];
}
顺便说一下,除非绝对必要,否则这是避免静态或全局变量的好习惯。