3

恰好函数使用本地缓冲区来准备一些大小有限的数据块并将其传递给另一个函数,就像这样:

void foo()
{
  char buffer[MAX_SIZE];
  size_t size = write_fancy_things(buffer);
  bar(buffer, size);
}

但是,根据 的值MAX_SIZE,您可能会担心会吃掉太多的堆栈,并用类似于以下示例的代码替换代码(但希望更关心内存管理):

void foo()
{
  static char *buffer = new char[MAX_SIZE]; 
  size_t size = write_fancy_things(buffer);
  bar(buffer, size);
}

在一般情况下,这两个函数的行为应该相同。但是,在第一个示例中,如果MAX_SIZE太大,我们更有可能达到堆栈限制。如果您知道函数的使用位置,则使用较大的值可能会很好,但有时您不知道。

在第二个示例中,我们正在处理额外的间接性,缓冲区更容易出现 CPU 缓存未命中,如果foo位于低延迟关键路径上,并且我们预计在大多数情况下准备缓冲区的成本非常低,则可能会出现这种情况.

您认为多大尺寸不能堆叠?将大块数据放在堆栈上但只使用其中的一小部分是否有任何惩罚?

编辑:write_fancy _things只是说*我正在将一些数据写入缓冲区的同义词,介于 1 和 MAX_SIZE 字节之间*。您可以将第二个foo示例视为类方法,将静态指针视为在构造函数中分配的类成员。我可能只是过度简化了事情,但不想引入比需要更多的复杂性并专注于堆栈问题。

4

4 回答 4

4

两者甚至根本不完全相同。第二个对所有调用使用相同的缓冲区,第一个使用新的缓冲区,这意味着第二个不是线程安全的。

风格太可怕了。如果 write_fancy_things 只使用 X 个字节,并且 X 在编译时未知,则动态分配 X 个字节。不要在堆栈上分配一些有希望的最大大小,也不要使用更大的有希望的最大大小的静态缓冲区。使用正确类型的向量,将其调整为适当的大小,然后使用该缓冲区。

于 2011-07-17T14:43:20.470 回答
2

将数据放入堆栈没有任何惩罚,因为您只是在递减堆栈指针。

堆栈大小可以使用操作系统实用程序修改,所以我不会担心高达 1MB 的大尺寸。

但我会担心递归调用。它们可能根本不会发生,因为它们会炸毁堆栈。

于 2011-07-17T14:42:16.457 回答
1

如果您开始担心大小,请选择堆,否则选择堆栈。

所有的情况都被考虑到了。

于 2011-07-17T14:46:52.740 回答
0

如果存在与帧边界冲突的问题(因为 MAX_SIZE 太大了),则转换为 std::vector

void foo()
{
  std::vector<char> buffer(MAX_SIZE);
  size_t size = write_fancy_things(&buffer[0]);
  bar(&buffer[0], size);
}

坦率地说,您的版本是非首发。

于 2011-07-17T16:20:59.313 回答