我如何知道内联函数是否在被调用的地方实际被替换?

时间:2012-05-17 07:02:10

标签: c++ inline

我知道内联函数要么被调用,要么被调用,或者表现为普通函数。

但是我怎么知道内联函数是否实际被替换在它被调用的地方,因为将内联函数作为内联处理的决定是在编译时?

10 个答案:

答案 0 :(得分:58)

在运行时以编程方式,你不能 事情的真相是: 你不需要知道

编译器可以选择inline未标记为inline的函数或忽略明确标记为inline的函数,这完全是希望(读取智慧)编译器&你应该相信编译器能够明智地完成它的工作。大多数主流编译器都能很好地完成它们的工作。

如果您的问题纯粹来自学术观点,那么有几种选择:


分析生成的汇编代码:

您可以检查汇编代码以检查函数代码是否在调用时内联。

如何生成汇编代码?

对于gcc:
编译时使用-S开关 例如:

g++ -S FileName.cpp

生成的汇编代码创建为文件FileName.s

对于MSVC:
从命令行使用 /FA Switch

在生成的汇编代码中查找是否存在特定函数的call汇编指令。


使用编译器特定的警告和诊断:

如果某些编译器未能遵守内联函数请求,则会发出警告 例如,在gcc中,如果编译器没有内联声明为内联的函数,-Winline命令选项将发出警告。

查看 GCC documentation 了解更多详情:

  

-Winline

     

如果无法内联声明为内联的函数,则发出警告。即使使用此选项,编译器也不会警告系统头中声明的内联函数失败。

     

编译器使用各种启发式方法来确定是否内联函数。例如,编译器会考虑内联函数的大小以及当前函数中已经完成的内联量。因此,源程序中看似无关紧要的更改可能会导致-Winline产生的警告出现或消失。

答案 1 :(得分:10)

检查生成的代码。如果函数被展开,你将看到它的主体,而不是call或类似的指令。

答案 2 :(得分:7)

您可以使用工具在Linux上列出目标文件中的符号,例如nm。如果函数是内联的,它将不会列在nm输出中 - 它成为其他函数的一部分。此外,您将无法在调试器中按名称将断点放在此函数上。

答案 3 :(得分:4)

使用gdb,如果你不能调用一个函数,它的一个可能含义是函数是内联的。翻转推理,如果你可以在gdb中调用一个函数,意味着该函数没有内联标记。

答案 4 :(得分:4)

如果您需要确保内联函数并且可以使用MS VC ++中的专有扩展,check out the __forceinline declarator。编译器将内联函数,或者,如果它属于记录的特殊情况列表,您将收到警告 - 因此您将知道内联状态。

不以任何方式支持它。

答案 5 :(得分:3)

内联或不是函数的决定由编译器决定。由于它是由编译器生成的,所以是的,它只能在编译时生成。

因此,如果您可以使用-S选项查看汇编代码(使用gcc -S生成汇编代码),您可以查看您的函数是否已内联。

答案 6 :(得分:0)

  1. 查看目标文件的大小,它们在内联和未内联之间是不同的
  2. 使用nm" obj_file" | grep" fun_name",它们也不同
  3. gcc -Winline -O1
  4. 与汇编代码比较

答案 7 :(得分:0)

以上回答非常有用,我只是在编写内联函数时添加了一些我们记在心里的观点。

请记住,内联只是对编译器的请求,而不是命令。编译器可以忽略内联请求。 编译器可能无法在

等情况下执行内联

1)如果函数包含循环。 (for,while,do-while)

2)如果函数包含静态变量。

3)如果函数是递归的。

4)如果函数返回类型不是void,并且函数体中不存在return语句。

5)如果函数包含switch或goto语句。

完整信息:https://www.geeksforgeeks.org/inline-functions-cpp/

答案 8 :(得分:0)

有一种方法可以确定函数是否以编程方式内联,而无需查看汇编代码。答案取自here

说您要检查是否内联特定呼叫。你会像这样去。编译器内联函数,但是对于那些导出的函数(几乎所有函数都是导出的),它需要维护一个非内联可寻址函数代码,该代码可以从外部调用。

要检查函数my_function是否内联,需要将my_function函数指针(未内联)与PC的当前值进行比较。这是我在环境中(GCC 7,x86_64)所做的操作:

void * __attribute__((noinline)) get_pc () { return _builtin_return_address(0); }

void my_function() {
    void* pc = get_pc();
    asm volatile("": : :"memory");
    printf("Function pointer = %p, current pc = %p\n", &my_function, pc);
}
void main() {
    my_function();
}

如果未内联函数,则PC的当前值与函数指针的值之间的差应较小,否则应较大。在我的系统上,当未内联my_function时,将得到以下输出:

Function pointer = 0x55fc17902500, pc = 0x55fc1790257b

如果函数是内联的,我得到:

Function pointer = 0x55ddcffc6560, pc = 0x55ddcffc4c6a

对于非内联版本差异为0x7b,对于内联版本差异为0x181f

答案 9 :(得分:-1)

如果函数返回一个地址,则编译器不会使其内联。