在检查以下功能的反汇编时,
void * malloc_float_align(size_t n, unsigned int a, float *& dizi)
{
void * adres=NULL;
void * adres2=NULL;
adres=malloc(n*sizeof(float)+a);
size_t adr=(size_t)adres;
size_t adr2=adr+a-(adr&(a-1u));
adres2=(void * ) adr2;
dizi=(float *)adres2;
return adres;
}
即使设置了inline
优化标志,也不会内联内置函数。
; Line 26
$LN4:
push rbx
sub rsp, 32 ; 00000020H
; Line 29
mov ecx, 160 ; 000000a0H
mov rbx, r8
call QWORD PTR __imp_malloc <------this is not inlined
; Line 31
mov rcx, rax
; Line 33
mov rdx, rax
and ecx, 31
sub rdx, rcx
add rdx, 32 ; 00000020H
mov QWORD PTR [rbx], rdx
; Line 35
add rsp, 32 ; 00000020H
pop rbx
ret 0
问题这是malloc
等函数的必备属性吗?我们可以用某种方式来检查它(或任何其他函数,如strcmp / new / free / delete)吗?这是禁止的吗?
答案 0 :(得分:2)
通常,编译器在编译期间具有可用的源代码(换句话说,在头文件中定义函数而不仅仅是原型声明)时将内联函数。
但是,在这种情况下,函数(malloc
)位于DLL中,因此在编译代码期间编译器无法使用源代码。它与malloc
所做的事情无关。但是,无论如何,malloc
也可能不会被内联,因为它是一个相当大的函数[至少它经常是],即使源代码可用,也会阻止它被内联。
如果您使用的是Visual Studio,几乎可以肯定找到运行时库的源代码,因为它随Visual Studio软件包提供。
(C运行时函数在DLL中,因为系统中的许多不同程序使用相同的函数,因此将它们放入为该功能的所有“用户”加载一次的DLL中将大大节省大小尽管malloc可能只有几百个字节,但像printf
这样的函数可以很容易地将大约5-25KB添加到可执行文件的大小。乘以“用户”的数量。 printf
,并且可能只有几百千字节来自“保存”的一个功能 - 当然还有所有其他功能,例如fopen
,fclose
,malloc
,{ {1}},calloc
等等都会为整体尺寸添加一点点数)
答案 1 :(得分:1)
允许C编译器内联malloc
(或者,正如您在示例中看到的那样,部分内容),但不是必需来内联任何内容。它使用的启发式方法无需记录,并且它们通常非常复杂,但通常只会内联短函数,因为否则可能会出现代码膨胀。
答案 2 :(得分:1)
malloc
和朋友在运行时库中实现,因此它们不可用于内联。他们需要在头文件中实现它们才能实现。
如果要查看它们的反汇编,可以使用调试器进入它们。或者,根据您使用的编译器和运行时,源代码可能可用。例如,它可用于gcc和msvc。
答案 3 :(得分:1)
阻止malloc()
等内联的主要原因是它们的复杂性 - 以及没有提供函数内联定义的明显事实。此外,您可能需要在不同时间使用不同版本的功能;像valgrind
这样的工具工作起来会更难(更麻烦),如果他们的代码是内联扩展的,你也无法安排使用这些函数的调试版本。