C 编译器可以重新排列堆栈变量吗?
我过去曾参与过嵌入式系统的项目,我们重新安排了堆栈变量的声明顺序以减小生成的可执行文件的大小.例如,如果我们有:
I have worked on projects for embedded systems in the past where we have rearranged the order of declaration of stack variables to decrease the size of the resulting executable. For instance, if we had:
void func()
{
char c;
int i;
short s;
...
}
我们会将其重新排序为:
We would reorder this to be:
void func()
{
int i;
short s;
char c;
...
}
由于对齐问题,第一个导致使用了 12 个字节的堆栈空间,而第二个导致仅使用了 8 个字节.
Because of alignment issues the first one resulted in 12 bytes of stack space being used and the second one resulted in only 8 bytes.
这是 C 编译器的标准行为还是我们使用的编译器的一个缺点?
Is this standard behavior for C compilers or just a shortcoming of the compiler we were using?
在我看来,如果编译器愿意,它应该能够重新排序堆栈变量以支持更小的可执行文件大小.有人建议我 C 标准的某些方面阻止了这种情况,但我无法找到有信誉的来源.
It seems to me that a compiler should be able to reorder stack variables to favor smaller executable size if it wanted to. It has been suggested to me that some aspect of the C standard prevents this, but I haven't been able to find a reputable source either way.
作为附加问题,这是否也适用于 C++ 编译器?
As a bonus question, does this also apply to C++ compilers?
编辑
如果答案是肯定的,C/C++ 编译器可以重新排列堆栈变量,你能举一个绝对做到这一点的编译器的例子吗?我想查看编译器文档或类似的东西来支持这一点.
If the answer is yes, C/C++ compilers can rearrange stack variables, can you give an example of a compiler that definitely does this? I'd like to see compiler documentation or something similar that backs this up.
再次编辑
感谢大家的帮助.对于文档,我能找到的最好的东西是论文 Optimal Stack Slot Assignment in GCC(pdf),作者 Naveen Sharma 和 Sanjiv Kumar Gupta,在 2003 年的 GCC 峰会上发表.
Thanks everybody for your help. For documentation, the best thing I've been able to find is the paper Optimal Stack Slot Assignment in GCC(pdf), by Naveen Sharma and Sanjiv Kumar Gupta, which was presented at the GCC summit proceedings in 2003.
这里讨论的项目是使用 ADS 编译器进行 ARM 开发.在该编译器的文档中提到,像我展示的排序声明可以提高性能以及堆栈大小,因为 ARM-Thumb 体系结构如何计算本地堆栈帧中的地址.该编译器不会自动重新排列本地变量以利用这一点.此处链接的论文说,截至 2003 年,GCC 也没有重新排列堆栈帧以改善 ARM-Thumb 处理器的引用局部性,但这意味着您可以.
The project in question here was using the ADS compiler for ARM development. It is mentioned in the documentation for that compiler that ordering declarations like I've shown can improve performance, as well as stack size, because of how the ARM-Thumb architecture calculates addresses in the local stack frame. That compiler didn't automatically rearrange locals to take advantage of this. The paper linked here says that as of 2003 GCC also didn't rearrange the stack frame to improve locality of reference for ARM-Thumb processors, but it implies that you could.
我找不到任何可以肯定地说这曾在 GCC 中实现过的东西,但我认为这篇论文可以证明你是正确的.再次感谢.
I can't find anything that definitely says this was ever implemented in GCC, but I think this paper counts as proof that you're all correct. Thanks again.
推荐答案
由于标准中没有禁止 C 或 C++ 编译器这样做,是的,编译器可以这样做.
As there is nothing in the standard prohibiting that for C or C++ compilers, yes, the compiler can do that.
聚合(即结构)是不同的,其中必须保持相对顺序,但编译器仍然可以插入填充字节以实现更好的对齐.
It is different for aggregates (i.e. structs), where the relative order must be maintained, but still the compiler may insert pad bytes to achieve preferable alignment.
IIRC 较新的 MSVC 编译器利用这种自由来对抗本地缓冲区溢出.
IIRC newer MSVC compilers use that freedom in their fight against buffer overflows of locals.
附带说明,在 C++ 中,即使编译器重新排序内存布局,销毁顺序也必须与声明相反.
As a side note, in C++, the order of destruction must be reverse order of declaration, even if the compiler reorders the memory layout.
(我不能引用章节和诗句,但这是凭记忆.)
(I can't quote chapter and verse, though, this is from memory.)
相关文章