4

存储具有恒定预定义大小(如缓冲区)的运行时数据的更好位置是:堆(malloc)、堆栈(例如char buf[BUFSIZE]在函数内部)或 bss 部分(char buf[BUFSIZE]在全局区域中)?

4

4 回答 4

6

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

通常应该避免使用全局变量,您必须非常小心,以免遇到它们带来的问题。

如果只有一个函数需要缓冲区并且 BUFSIZE 不是太大(最大几 KB),则可以将其设为本地。但是,请注意总堆栈使用情况,因为嵌套调用加起来。仅当您想在调用之间保留值时才需要静态本地,从而有效地使其成为具有本地范围的全局。但是当您使用多线程或想要使用递归时,它会让您头疼。

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

从更大的角度来看,当您的程序增长时,您希望赋予它更多结构并明确定义职责,尤其是。用于内存处理,否则您最终会迷失方向。该缓冲区是具有特定任务的特定模块的工作细节。一种典型的方法是使用结构以 OOP 方式组织数据,并使用创建和销毁函数来分配和释放这样的对象。然后缓冲区可以成为该结构的一部分。

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

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

于 2012-10-25T11:49:12.703 回答
1

在这种情况下,如果缓冲区不在函数之间共享,IMO 最好的选择是局部静态变量:

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

这避免了重复分配/解除分配和命名空间混乱。

编辑

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

于 2012-10-25T07:52:35.007 回答
0

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

于 2012-10-25T06:59:47.110 回答
0

显然,堆是因为大小是有限的。我也不会选择静态,因为它们不是可重入的,并且会给递归带来严重破坏。所以,把它放在堆栈帧中。

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

顺便说一句,除非绝对必要,否则避免静态或全局变量是一种很好的做法。

于 2012-10-25T11:12:13.617 回答