GCC';s`\u内置的`\u malloc()`在普通的` malloc()`上提供吗?
最近,我了解到GCC的一些内置函数用于C库的内存管理函数,特别是GCC';s`\u内置的`\u malloc()`在普通的` malloc()`上提供吗?,c,gcc,C,Gcc,最近,我了解到GCC的一些内置函数用于C库的内存管理函数,特别是\uuu builtin\u malloc()和相关的内置函数(请参阅)。在学习了\uuuu内置的
\uuu builtin\u malloc()
和相关的内置函数(请参阅)。在学习了\uuuu内置的
之后,我想知道它是如何在普通的malloc()
相关库例程的基础上提供性能改进的
例如,如果函数成功,它必须提供一个可以通过调用plainfree()
来释放的块,因为指针可能会被编译时未启用\uuuuubuiltin\umalloc()
或\ubuiltin\ufree()
的模块释放(或者我错了,如果\ubuiltin\umalloc()如果使用了
,则必须全局使用内置?)。因此,分配的对象必须是可以用普通的malloc()
和free()
处理的数据结构进行管理的对象
我找不到任何关于\uu builtin\u malloc()
如何工作或它到底做什么的详细信息(我不是一个编译器开发人员,所以深入研究GCC源代码并不在我的掌握之中)。在一些简单的测试中,我尝试直接调用\uu builtin\u malloc()
,它只是在目标代码中作为对plainmalloc()
的调用发出。然而,在这些简单的测试中,可能有一些我没有提供的微妙之处或平台细节
通过调用plainmalloc()
可以提供哪些性能改进?\uuu内置的\uMalloc()
是否依赖于glibc的malloc()实现所使用的相当复杂的数据结构?或者相反,glibc的malloc()
/free()
是否有一些代码来处理可能由\uuuu内置的\uMalloc()分配的块
基本上,它是如何工作的?我认为,\uuuu builtin\umalloc()
没有特殊的GCC内部实现。相反,它作为一个内置项存在,只是为了在某些情况下可以对其进行优化
举个例子:
#include <stdlib.h>
int main(void)
{
int *p = malloc(4);
*p = 7;
free(p);
return 0;
}
按预期发出对malloc
/free
的调用
但是,通过允许malloc
成为内置的
$gcc-O1-Wall-Wextra builtin_malloc.c&&objdump-d-Mintel a.out
0000000000 4004F0:
4004f0:B800 mov eax,0x0
4004f5:c3 ret
所有的main()
都被优化掉了
本质上,通过允许malloc
成为一个内置函数,GCC可以在其结果从未被使用的情况下自由地消除调用,因为没有额外的副作用
这与允许将对printf
的“浪费”调用更改为对put
的调用的机制相同:
#include <stdio.h>
int main(void)
{
printf("hello\n");
return 0;
}
#包括
内部主(空)
{
printf(“hello\n”);
返回0;
}
内置禁用:
$gcc-fno builtin-O1-Wall builtin_printf.c&&objdump-d-Mintel a.out
0000000000400530 :
400530:48 83 ec 08子rsp,0x8
400534:bf e0 05 40 00 mov edi,0x4005e0
400539:B800 mov eax,0x0
40053e:e8 cd fe ff ff呼叫400410
400543:B800 mov eax,0x0
400548:48 83 c4 08添加rsp,0x8
40054c:c3 ret
已启用内置:
gcc-O1-Wall-builtin_printf.c&&objdump-d-Mintel a.out
0000000000400530 :
400530:48 83 ec 08子rsp,0x8
400534:bf e0 05 40 00 mov edi,0x4005e0
400539:e8 d2 fe ff ff呼叫400410
40053e:B800 mov eax,0x0
400543:48 83 c4 08添加rsp,0x8
400547:c3 ret
有趣且有用的解释。因此,内置版本的基本功能是,它可以保证编译器的已知行为,从而允许对其进行优化,或许还可以接受其他优化…@DanLenski我就是这么看的。经过多次实验,我唯一能让GCC对\uuu builtin\u malloc
做“特殊”的事情就是对其进行优化。我尝试传递它0
,但将结果传递给另一个(外部)函数会导致发出对malloc
的调用。编译器可能知道内置malloc的结果不会与任何其他指针别名。假设您的函数使用int*p作为参数,并调用int*q=malloc(sizeof int)*q=1;然后编译器知道这个赋值没有修改*p。您在回答中提示的是,但明确声明有用的是,对声明函数malloc
的调用通常被转换为对\u builtin\u malloc
的调用,而对\uuuu内置\umalloc
的调用通常被转换为对外部库函数malloc
的调用。您描述了其中的第二部分,但第一部分也是相关的:它很重要,因为它表明用户几乎不需要实际拼写\uuuuuu builtin\umalloc
:即使用户只使用普通的malloc
,它也可以工作。