GCC编译器在优化级别O0下无法找到内联函数定义的链接问题?-灵析社区

小青梅

## GCC编译器在优化级别O0下无法找到内联函数定义的链接问题 我在gcc编译器下写了如下代码: /* InlineMain.c */ #include inline void Function() { printf("[Function]========= Get!!!\n"); } int main() { Function(); return 0; } 然后在不开启优化(即-O0)的情况下,会报链接错误,找不到符号"Function": * 备注:在开启优化O1以上的情况下是可以正常编译的,编译器会将函数体进行替换 $ gcc INlineMain.c /usr/bin/ld: /tmp/ccQuzijl.o: in function `main': INlineMain.c:(.text+0xe): undefined reference to `Function' collect2: error: ld returned 1 exit status 我试着编译并查看了对应的汇编代码: > $ gcc INlineMain.c -S > $ cat INlineMain.s .file "INlineMain.c" .text .globl main .type main, @function main: .LFB1: .cfi_startproc endbr64 pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $0, %eax call Function@PLT movl $0, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1: .size main, .-main .ident "GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0" .section .note.GNU-stack,"",@progbits .section .note.gnu.property,"a" .align 8 .long 1f - 0f .long 4f - 1f .long 5 0: .string "GNU" 1: .align 8 .long 0xc0000002 .long 3f - 2f 2: .long 0x3 3: .align 8 4: 然后我就发现一件非常让我匪夷所思的事情,就是**整一个Function函数主体都消失了!!!** 但是也没有被内联替换到被调用的地方,不难发现,在main函数中,依旧是: > call Function@plt, 即把Function函数当做plt表里的函数(也就是外部函数调用) , 看上去就像是在处理Function函数体的时候编译器把它当做是要内联的函数处理,于是就把整个函数体给删除了,但是在处理函数调用的时候又没有把函数体进行替换,而是把它当做正常的函数调用处理,就好像是处理到中途反悔了一样,有没有大佬能解释一下是为什么? * 备注:我的平台是ubuntu22.04,gcc编译器是默认的版本

阅读量:178

点赞量:0

问AI
C99 对 inline 有一个这样的"说明" (https://link.segmentfault.com/?enc=GujapjpbuFVNbVdkUJ3y2w%3D%3D.aVOECZxu3KHabs8UsfUVigVYcNZgG13n%2B3%2Be%2BlginK7%2FpLC46bH6Fmi5qjG9RMuv): «Any function with internal linkage can be an inline function. For a function with external linkage, the following restrictions apply: If a function is declared with an inline function specifier, then it shall also be defined in the same translation unit. If all of the file scope declarations for a function in a translation unit include the inline function specifier without extern, then the definition in that translation unit is an inline definition. An inline definition does not provide an external definition for the function, and does not forbid an external definition in another translation unit. An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition.» 一个函数可以有一个 inline definition 和一个 external definition ,而且编译器可以自由选择在调用时使用哪一种。注意不是去看哪一种存在,而是先决定用哪一种,再去看它是不是存在。 这里出错是因为编译器决定用 external definition (-O0 阻止了内连),但是程序中只有一个 inline definition ,并没有 external definition ,于是出错了。 注意 C++ 中 inline 的用法并不是这样的,gcc 也有其它的 inline 模式。 另可参考: "https://gcc.gnu.org/gcc-5/porting_to.html" (https://link.segmentfault.com/?enc=v%2BfTcHSOkSHCiooLn%2BMBKg%3D%3D.ff07gQxwL6cm1mJjgaZXE6Q%2Bx6ly9bosHqWXrx9TMAX5pTqS83JhwRPYSz7xuD50) (Different semantics for inline functions)