2013-07-28 111 views
1

在考察下面的功能的拆卸,C/C++编译器可以内联malloc()内联函数吗?

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

被谁禁止?该标准不涉及这些实施细节。 – delnan

+0

由编译器。我怎样才能让他们内联? –

+0

如果只有一个调用者,或者被调用函数的复杂度小于调用本身的复杂度,则内联是最有益的。 'malloc'几乎与这个尺度的两端相反。 – MSalters

回答

2

通常,所述编译器将内联函数时,它具有在编译期间可用的源代码(换言之,该函数被定义,而不是仅仅一个原型说明)在头文件中)。

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

如果您正在使用Visual Studio,你可以几乎肯定找到适合您的运行时库的源代码,因为它是与Visual Studio封装。因为系统中的许多不同程序都使用相同的函数,因此将它们放入一个为所有功能的“用户”加载一次的DLL中将会很好地节省尽管malloc可能只有几百字节,但像printf这样的函数可以很容易地为可执行文件的大小增加5-25KB,乘以printf的“用户”数量和有可能是几百千字节刚刚从一个功能“节省” - 当然,所有其他功能,如fopenfclosemalloccallocfree,等所有每加一点点的整体尺寸)

+0

好的,我有使用malloc的函数包的dll。我怎样才能打开DLL看到的成分?例如:第135行:malloc_starts_here,第1040行:END malloc –

+0

如果您使用调试器[并且您已启用调试符号]将其单个设置为它,则它应该为您提供源代码。 –

1

C编译器允许内联malloc(或者,如您在示例中看到的那样,它的一部分),但不需要需要来内联任何东西。它使用的启发式方法不需要记录,它们通常非常复杂,但通常只有简短的函数会被内联,因为否则可能会导致代码膨胀。

1

malloc和朋友在运行时库中实现,所以他们没有可用的内联。他们需要在他们的头文件中实现它们,以实现这一点。

如果你想看到他们的拆装,你可以走进他们与调试。或者,根据您使用的编译器和运行时,源代码可能是可用的。例如,它可用于gcc和msvc。

1

最主要停止malloc()等人的内联是其复杂性 - 而这是提供的功能没有内嵌定义一个明显的事实。此外,您可能需要不同版本的功能在不同的时间;对于像valgrind这样的工具来说工作起来会更困难(更麻烦),并且如果他们的代码以内联方式展开,则无法安排使用调试版本的功能。