将其放在堆栈中或放在堆中

leave it on stack or put in on heap?

本文关键字:堆栈      更新时间:2023-10-16

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

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位于低延迟关键路径上的情况,并且我们期望在大多数情况下准备缓冲区的成本非常低。

你认为什么尺寸的文件太大而不能放到堆栈中?另外,如果将大数据块放在堆栈上,但只使用其中的一小部分,会有什么损失吗?

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

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

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

将数据放在堆栈上没有任何损失,因为您只是在减少堆栈指针。

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

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

如果你开始担心大小,那就堆,否则堆栈。

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

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

坦率地说,你的版本是行不通的。