我相信沒有特殊的GCC內部實現__builtin_malloc()
。相反,它僅作爲內建使用,因此在某些情況下可以優化它。
藉此例如:
#include <stdlib.h>
int main(void)
{
int *p = malloc(4);
*p = 7;
free(p);
return 0;
}
如果我們禁用建宏(與-fno-builtins
),並期待在所生成的輸出:
$ gcc -fno-builtins -O1 -Wall -Wextra builtin_malloc.c && objdump -d -Mintel a.out
0000000000400580 <main>:
400580: 48 83 ec 08 sub rsp,0x8
400584: bf 04 00 00 00 mov edi,0x4
400589: e8 f2 fe ff ff call 400480 <[email protected]>
40058e: c7 00 07 00 00 00 mov DWORD PTR [rax],0x7
400594: 48 89 c7 mov rdi,rax
400597: e8 b4 fe ff ff call 400450 <[email protected]>
40059c: b8 00 00 00 00 mov eax,0x0
4005a1: 48 83 c4 08 add rsp,0x8
4005a5: c3 ret
呼叫至malloc
/free
被髮射,如所預期。
然而,通過允許malloc
是一個內置的,
$ gcc -O1 -Wall -Wextra builtin_malloc.c && objdump -d -Mintel a.out
00000000004004f0 <main>:
4004f0: b8 00 00 00 00 mov eax,0x0
4004f5: c3 ret
所有main()
被優化掉!
實質上,通過允許malloc
成爲內置函數,GCC可以自由地消除從未使用過的調用,因爲沒有附加的副作用。
這是相同的機制,允許 「浪費」 呼籲printf
被改爲調用puts
:
#include <stdio.h>
int main(void)
{
printf("hello\n");
return 0;
}
內建命令禁用:
$ gcc -fno-builtin -O1 -Wall builtin_printf.c && objdump -d -Mintel a.out
0000000000400530 <main>:
400530: 48 83 ec 08 sub rsp,0x8
400534: bf e0 05 40 00 mov edi,0x4005e0
400539: b8 00 00 00 00 mov eax,0x0
40053e: e8 cd fe ff ff call 400410 <[email protected]>
400543: b8 00 00 00 00 mov eax,0x0
400548: 48 83 c4 08 add rsp,0x8
40054c: c3 ret
內置命令啓用:
gcc -O1 -Wall builtin_printf.c && objdump -d -Mintel a.out
0000000000400530 <main>:
400530: 48 83 ec 08 sub rsp,0x8
400534: bf e0 05 40 00 mov edi,0x4005e0
400539: e8 d2 fe ff ff call 400410 <[email protected]>
40053e: b8 00 00 00 00 mov eax,0x0
400543: 48 83 c4 08 add rsp,0x8
400547: c3 ret
有趣和有用的解釋。所以內置版本的基本特點是它可以保證編譯器有一個已知的行爲,從而可以優化它,也可以接受其他優化... – 2014-09-24 06:36:12
@DanLenski這就是我所看到的。經過大量實驗後,我可以讓GCC用'__builtin_malloc'做「特殊」的唯一事情就是優化它。我嘗試傳遞它'0',但將結果傳遞給另一個(外部)函數導致調用'malloc'來發射。 – 2014-09-24 06:38:30
編譯器可能知道__builtin_malloc的結果不會與任何其他指針一起使用。假設你的函數有int * p作爲參數並且調用int * q = malloc(sizeof int); * q = 1;那麼編譯器知道這個賦值沒有修改* p。 – gnasher729 2014-09-24 09:34:17