简体   繁体   English

C 标准是否对使用的堆栈空间量有任何保证?

[英]Does the C standard have any guarantees on the amount of stack space used?

I am doing embedded programming where saving memory is important.我正在做嵌入式编程,其中节省内存很重要。

How much stack space would the following C code occupy at run-time?以下 C 代码在运行时会占用多少堆栈空间?

if (send_small_message) {
    uint8_t buffer[16000];
    // do something with the buffer
} else {
    uint8_t buffer[32000];
    // do something the with buffer
}

Could some compiler decide to allocate 16000 + 32000 = 48kB stack space for both buffers?某些编译器能否决定为两个缓冲区分配 16000 + 32000 = 48kB 堆栈空间? Or is it guaranteed that since both buffers will never be used at the same time, the compiler will allocate only 32kB - the size of the larger buffer?或者是否保证因为两个缓冲区永远不会同时使用,编译器将只分配 32kB - 较大缓冲区的大小?

FOLLOW UP QUESTION:跟进问题:

void SendSmallMessage() {
    uint8_t buffer[16000];
    // do something with the buffer
}

void SendLargeMessage() {
    uint8_t buffer[32000];
    // do something with the buffer
}

Can a code compiled by some compiler use 16000 + 32000 bytes at run-time to execute the snippet below:某些编译器编译的代码是否可以在运行时使用 16000 + 32000 字节来执行以下代码段:

if (send_small_message) {
   SendSmallMessage(); 
} else {
   SendLargeMessage();
}

Does the C standard guarantee amount of stack used? C 标准是否保证使用的堆栈数量?

No guarantees whatsoever exist for this.对此不存在任何保证。 The C standard does not mention concepts like stacks. C 标准没有提到像栈这样的概念。 You can even write C for low level CPUs that completely lack a stack.您甚至可以为完全没有堆栈的低级 CPU 编写 C。

The C standard does however guarantee that uint8_t is 1 byte large and that 1 byte is 8 bits on your system (or otherwise uint8_t wouldn't be available).然而,C 标准确实保证uint8_t是 1 字节大,并且 1 字节是系统上的 8 位(否则uint8_t将不可用)。

How much stack space would the following C code occupy at run-time?以下 C 代码在运行时会占用多少堆栈空间?
Could some compiler decide to allocate 16000 + 32000 = 48kB stack space for both buffers?某些编译器能否决定为两个缓冲区分配 16000 + 32000 = 48kB 堆栈空间?

System-specific, but also depends on exactly how the function is written and what optimizations that take place.特定于系统,但也取决于函数的编写方式和发生的优化。 Generally though, real world systems allocate room for as much stack as the function requires, given all possible execution paths.但是,一般来说,在给定所有可能的执行路径的情况下,现实世界的系统为函数所需的堆栈分配空间。 So it is quite likely that many compilers would allocate 16k + 32k.所以很可能许多编译器会分配 16k + 32k。

But who cares, since it doesn't make sense to allocate that large amount of memory on the stack in any known system.但谁在乎呢,因为在任何已知系统的堆栈上分配大量内存都没有意义。 Not on high-end, PC-like systems and certainly not on memory-restricted embedded systems.不是在高端的类似 PC 的系统上,当然也不是在内存受限的嵌入式系统上。 You'll get stack overflows all over the place.你会到处都是堆栈溢出。

The general rule of thumb in embedded is to never allocate any form of buffers on the stack, but always with static storage duration.嵌入式中的一般经验法则是永远不要在堆栈上分配任何形式的缓冲区,而是始终具有静态存储持续时间。 On PC-like systems, heap allocation is another option.在类似 PC 的系统上,堆分配是另一种选择。

@Lundin provided an excellent answer . @Lundin 提供了一个很好的答案 But I wanted to answer from a slightly different perspective.但我想从稍微不同的角度来回答。

The C standard basically guarantees behavior of the code. C 标准基本上保证了代码的行为 It does not guarantee much of how it is done.它并不能保证它是如何完成的。 It is possible (don't know how likely) that it will even move the buffer declaration outside the if statement.它甚至有可能(不知道有多大可能)将缓冲区声明移到 if 语句之外。 It may also allocate more memory than specified.它也可能分配比指定更多的内存。 It is also allowed to allocate less if it does not break anything.如果它不破坏任何东西,也允许分配更少。 Typically, unused variables are removed by the optimizer.通常,优化器会删除未使用的变量。 The optimizer also often inline small functions instead of calling them, and it may change a printf("\\n") to a puts("") .优化器还经常内联小函数而不是调用它们,并且它可能将printf("\\n")更改为puts("") The compiler is free to do anything as long as the observable behavior of the code remains the same.只要代码的可观察行为保持不变,编译器就可以自由地做任何事情。

So no, you don't have any guarantees in this case.所以不,在这种情况下你没有任何保证。

But one thing to consider here.但这里要考虑一件事。 You want to declare a different sized buffer depending on an if statement.您想根据 if 语句声明不同大​​小的缓冲区。 Let's say that these extra 16kB would invoke a stack overflow.假设这些额外的 16kB 会引起堆栈溢出。 What do you do if you have less than 32kB of stack left and the else branch needs to be executed?如果剩余的堆栈少于 32kB 并且需要执行 else 分支,您会怎么做? Of course it depends on how the code is used in reality, but it is definitely worth considering.当然这取决于代码在现实中的使用方式,但绝对值得考虑。 To me, this is a pretty strong code smell.对我来说,这是一种非常强烈的代码味道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM