在大多數平臺上,alloca
只是歸結爲堆棧指針的內聯調整(例如,從x64上的rsp
減去另外一些邏輯以保持堆棧對齊)。gcc處理alloca有什麼用?
我在看代碼gcc
爲alloca生成,這很奇怪。看看下面的簡單例子:
#include <alloca.h>
#include <stddef.h>
volatile void *psink;
void func(size_t x) {
psink = alloca(x);
}
這編譯成以下大會-O2
:
func(unsigned long):
push rbp
add rdi, 30
and rdi, -16
mov rbp, rsp
sub rsp, rdi
lea rax, [rsp+15]
and rax, -16
mov QWORD PTR psink[rip], rax
leave
ret
這裏有幾個令人困惑的事情。我知道gcc
需要將分配的大小舍入爲16的倍數(以保持堆棧對齊),通常的方法是(size + 15) & ~0xF
,但是相反,它會在add rdi, 30
處增加30個?那是怎麼回事?
其次,我只希望alloca
的結果是新的rsp
值,該值已經很好地一致。取而代之的是,gcc在此:
lea rax, [rsp+15]
and rax, -16
這似乎是「重新調整」的rsp
價值爲alloca
結果使用 - 但我們已經做了對齊rsp
到16字節邊界在第一工作地點。
這是怎麼回事?你可以玩on godbolt。值得注意的是,clang
和icc
至少在x86上做了「預期的事情」。有了VLA(如之前的評論中所建議的),gcc
和clang
沒有問題,而icc
產生了可憎的。
1這裏,分配給psink
只是消耗的alloca
結果,因爲否則編譯器只是省略了它完全。
評論是不適合擴展討論;這個對話已經[轉移到聊天](http://chat.stackoverflow.com/rooms/136822/discussion-on-question-by-beeonrope-whats-up-with-gccs-handling-of-alloca)。 –