将其放在堆栈上还是放在堆上?
碰巧函数使用本地缓冲区准备一些有限大小的数据块并将其传递给另一个函数,就像这样:
void foo()
{
char buffer[MAX_SIZE];
size_t size = write_fancy_things(buffer);
bar(buffer, size);
}
但是,根据 MAX_SIZE
的值,您可能会担心吃太多much stack 并将代码替换为类似于以下示例的代码(但希望更加关心内存管理):
void foo()
{
static char *buffer = new char[MAX_SIZE];
size_t size = write_fancy_things(buffer);
bar(buffer, size);
}
在一般情况下,这两个函数应该表现相同。但是,在第一个示例中,如果 MAX_SIZE 太大,我们更有可能达到堆栈限制。如果您知道该函数的使用位置,那么使用较大的值可能没问题,但有时您并不知道。
在第二个示例中,我们正在处理额外的间接寻址,并且缓冲区更容易出现 CPU 缓存未命中的情况,如果 foo
位于低延迟关键路径上,并且我们预计准备 foo 的成本,则可能会出现这种情况。大多数情况下缓冲区非常低。
您认为什么尺寸太大而无法堆叠?将大数据块放入堆栈但只使用其中的一小部分是否会受到任何惩罚?
编辑: write_fancy _things
只是“我正在向缓冲区写入一些数据(介于 1 到 MAX_SIZE 字节之间)”的同义词。您可以将第二个 foo 示例视为类方法,并将静态指针视为在构造函数中分配的类成员。我可能只是把事情过于简单化了,但不想引入比需要更多的复杂性,并专注于堆栈问题。
It happens that function uses local buffer to prepare some block of data of limited size and pass it to the other function, just like this:
void foo()
{
char buffer[MAX_SIZE];
size_t size = write_fancy_things(buffer);
bar(buffer, size);
}
However, depending on value of MAX_SIZE
, you might be worried about eating too much stack and replace the code with something similar to the following example (but hopefully with more care about memory management):
void foo()
{
static char *buffer = new char[MAX_SIZE];
size_t size = write_fancy_things(buffer);
bar(buffer, size);
}
In general case, these two functions should behave the same. However, in the first example, if MAX_SIZE
is too large, we're more likely to hit stack limit. Using large values might be fine if you're aware where the function is used, but sometimes you're not.
In the second example we're dealing with additional indirection and buffer is more prone to CPU cache miss, which may be a case if foo
lies on a low latency critical path and we expect the cost of preparing the buffer to be very low in most cases.
What size would you consider as being too large to put on stack? Also is there any penalty on putting big block of data on the stack, but using only small portion of it?
EDIT: The write_fancy _things
is just a synonym for saying *I'm writing some data to the buffer, between 1 and MAX_SIZE bytes*. You can think about the second foo
example as a class method, and the static pointer as a class member allocated in constructor. I've just probably oversimplified things, but didn't want to introduce more complexity than needed and focus on the stack concerns.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
将数据放入堆栈不会有任何损失,因为您只是递减堆栈指针。
堆栈大小可以使用操作系统实用程序进行修改,因此我不担心高达 1MB 左右的大大小。
但我会担心递归调用。它们可能根本不会发生,因为它们会炸毁堆栈。
There is no penalty for putting data on the stack because you are just decrementing the stack pointer.
The stack size can be modified using OS utilities, so I would not worry about big sizes up to about 1MB.
but I would worry about recursive calls. They may simply not happen because they will blow up the stack.
如果您开始担心大小,请考虑堆,否则考虑堆栈。
考虑到所有事情。
If you start worrying about size go for the heap, otherwise stack.
all things considered.
如果存在与帧边界冲突的问题(因为 MAX_SIZE 太大),则转换为 std::vector
坦率地说,您的版本是不可能的。
If there was a problem clashing with the frame boundary (because MAX_SIZE was way to big) then convert to std::vector
To be blunt your version is a non starter.
两者甚至完全不一样。第二个对所有调用使用相同的缓冲区,第一个使用新的缓冲区,这意味着第二个不是线程安全的。
风格太可怕了。如果 write_fancy_things 仅使用 X 个字节,并且 X 在编译时未知,则动态分配 X 个字节。不要在堆栈上分配一些希望的最大大小,并且不要使用更大的希望最大大小的静态缓冲区。使用正确类型的向量,将其大小调整为适当的大小,然后使用该缓冲区。
The two are not even remotely identical. The second one uses the same buffer for all calls, the first uses a new buffer, meaning that the second is not thread-safe.
The style is horrendous. If write_fancy_things only uses X many bytes, and X is unknown at compile-time, then dynamically allocate X bytes. Do not allocate some hopeful maximum size on the stack and do not use a static buffer of a larger hopeful maximum size. Use a vector of the correct type, resize it to the appropriate size, and then use that buffer.