存储具有恒定预定义大小(如缓冲区)的运行时数据的更好位置是:堆(malloc)、堆栈(例如char buf[BUFSIZE]
在函数内部)或 bss 部分(char buf[BUFSIZE]
在全局区域中)?
4 回答
这取决于你想用缓冲区做什么。
通常应该避免使用全局变量,您必须非常小心,以免遇到它们带来的问题。
如果只有一个函数需要缓冲区并且 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,每个都有自己的缓冲区,彼此独立。此外,缓冲区内容在调用之间保留,没有静态变量的麻烦。
在这种情况下,如果缓冲区不在函数之间共享,IMO 最好的选择是局部静态变量:
void func(...) {
static char buf[BUFSIZE];
}
这避免了重复分配/解除分配和命名空间混乱。
编辑
这个解决方案不是线程安全的,但全局变量也不是。
您需要一个在加载时分配并在程序生命周期内保持不变的静态变量。所以选项三,所谓的“bss”部分。
显然,堆是因为大小是有限的。我也不会选择静态,因为它们不是可重入的,并且会给递归带来严重破坏。所以,把它放在堆栈帧中。
void f(...) {
char buf[BUFSIZE];
}
顺便说一句,除非绝对必要,否则避免静态或全局变量是一种很好的做法。