C / C ++编译器可以内联函数如malloc()吗?

时间:2013-07-28 20:04:54

标签: c++ disassembly built-in

在检查以下功能的反汇编时,

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)吗?这是禁止的吗?

4 个答案:

答案 0 :(得分:2)

通常,编译器在编译期间具有可用的源代码(换句话说,在头文件中定义函数而不仅仅是原型声明)时将内联函数。

但是,在这种情况下,函数(malloc)位于DLL中,因此在编译代码期间编译器无法使用源代码。它与malloc所做的事情无关。但是,无论如何,malloc也可能不会被内联,因为它是一个相当大的函数[至少它经常是],即使源代码可用,也会阻止它被内联。

如果您使用的是Visual Studio,几乎可以肯定找到运行时库的源代码,因为它随Visual Studio软件包提供。

(C运行时函数在DLL中,因为系统中的许多不同程序使用相同的函数,因此将它们放入为该功能的所有“用户”加载一次的DLL中将大大节省大小尽管malloc可能只有几百个字节,但像printf这样的函数可以很容易地将大约5-25KB添加到可执行文件的大小。乘以“用户”的数量。 printf,并且可能只有几百千字节来自“保存”的一个功能 - 当然还有所有其他功能,例如fopenfclosemalloc,{ {1}},calloc等等都会为整体尺寸添加一点点数)

答案 1 :(得分:1)

允许C编译器内联malloc(或者,正如您在示例中看到的那样,部分内容),但不是必需来内联任何内容。它使用的启发式方法无需记录,并且它们通常非常复杂,但通常只会内联短函数,因为否则可能会出现代码膨胀。

答案 2 :(得分:1)

malloc和朋友在运行时库中实现,因此它们不可用于内联。他们需要在头文件中实现它们才能实现。

如果要查看它们的反汇编,可以使用调试器进入它们。或者,根据您使用的编译器和运行时,源代码可能可用。例如,它可用于gcc和msvc。

答案 3 :(得分:1)

阻止malloc()等内联的主要原因是它们的复杂性 - 以及没有提供函数内联定义的明显事实。此外,您可能需要在不同时间使用不同版本的功能;像valgrind这样的工具工作起来会更难(更麻烦),如果他们的代码是内联扩展的,你也无法安排使用这些函数的调试版本。