GCC';s`\u内置的`\u malloc()`在普通的` malloc()`上提供吗?

GCC';s`\u内置的`\u malloc()`在普通的` malloc()`上提供吗?,c,gcc,C,Gcc,最近,我了解到GCC的一些内置函数用于C库的内存管理函数,特别是\uuu builtin\u malloc()和相关的内置函数(请参阅)。在学习了\uuuu内置的

最近,我了解到GCC的一些内置函数用于C库的内存管理函数,特别是
\uuu builtin\u malloc()
和相关的内置函数(请参阅)。在学习了
\uuuu内置的
之后,我想知道它是如何在普通的
malloc()
相关库例程的基础上提供性能改进的

例如,如果函数成功,它必须提供一个可以通过调用plain
free()
来释放的块,因为指针可能会被编译时未启用
\uuuuubuiltin\umalloc()
\ubuiltin\ufree()
的模块释放(或者我错了,如果
\ubuiltin\umalloc()如果使用了
,则必须全局使用内置?)。因此,分配的对象必须是可以用普通的
malloc()
free()
处理的数据结构进行管理的对象

我找不到任何关于
\uu builtin\u malloc()
如何工作或它到底做什么的详细信息(我不是一个编译器开发人员,所以深入研究GCC源代码并不在我的掌握之中)。在一些简单的测试中,我尝试直接调用
\uu builtin\u malloc()
,它只是在目标代码中作为对plain
malloc()
的调用发出。然而,在这些简单的测试中,可能有一些我没有提供的微妙之处或平台细节

通过调用plain
malloc()
可以提供哪些性能改进?
\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
,它也可以工作。