2

在检查以下功能的拆卸时,

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

4 回答 4

3

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

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

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

(C 运行时函数位于 DLL 中,因为系统中的许多不同程序使用相同的函数,因此将它们放在为所有“用户”加载一次的 DLL 中可以很好地节省所有系统中的代码。虽然 malloc 可能只有几百字节,但像这样的函数printf可以轻松地将可执行文件的大小增加 5-25KB。乘以“用户”的数量,printf可能有几百 KB只是从那个“保存”的一个函数中 - 当然,所有其他函数,如fopen, fclose, malloc, calloc,free等等都会在整体大小上增加一点点)

于 2013-07-28T20:11:43.023 回答
1

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

于 2013-07-28T20:10:25.107 回答
1

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

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

于 2013-07-28T20:10:26.253 回答
1

阻止 et al 的内联的主要因素malloc()是它们的复杂性——以及一个明显的事实,即没有提供函数的内联定义。此外,您可能在不同时间需要不同版本的功能;对于喜欢工作的工具来说,它会更难(更混乱),valgrind如果它们的代码是内联扩展的,你就不能安排使用函数的调试版本。

于 2013-07-28T20:10:27.123 回答