0

包含多个标题“ah”中的此代码:

    __forceinline void f(void){}
    

在每个包含 'ah' 的对象文件中生成一个函数符号 - 测试对象是:

    #include "a.h"
    void f1(void) { f(); }

使用 Visual Studio 2019 (Community Ed.) v16.10.1 将其编译为目标文件:

$ CL /std:c17 /TC /O2 /c t_inl_a.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30037 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

t_inl_a.c
$
$ DUMPBIN /SYMBOLS t_inl_a.obj
Microsoft (R) COFF/PE Dumper Version 14.29.30037.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file t_inl_a.obj

File Type: COFF OBJECT

COFF SYMBOL TABLE
...
00E 00000000 SECT3  notype ()    External     | _f
00F 00000000 SECT5  notype ()    External     | _f1
...

MSYS2 binutils 'nm' 工具还报告一个外部 'T f' 符号。

我试图在 MSVC 中找到与 GCC 等效的东西

    __attribute__((always_inline))

,当上述代码由 gcc v11 编译时,将 __forceinline 替换为属性((always_inline)) 和任何 -Ox 优化级别 x > 0 ,它不会为上述 f() 函数生成任何函数符号。

我比 MSVC 更习惯 GCC。

任何 MSVC 专家能否指出我如何使用 MSVC 生成无符号的始终集成到调用者函数的函数,当代码中没有函数的地址时,它不是采用可变参数,并且不是递归的(C 标准规定函数可以内联的条件)?

经过数小时搜索 MSVC 文档和网络后,这在我看来是不可能的。

对我来说,使用 __forceline / __attribute__((always_inline))
的全部意义在于:

A)不生成符号,因此没有多重定义符号或链接问题,并且不必考虑符号应该在哪个对象/库中定义 - (特别是对于 Windows,是否需要 __declspec( dllexport)与否)。没有符号,因此没有与符号链接相关的问题。

B)代码只在使用时实例化,不使用时消耗0字节

C)没有函数调用/返回开销(首先是内联的整个点)-但是这种节省通过寄存器保存+恢复代码有所减少-(但大多数函数调用/返回机制也保存+恢复寄存器)。

MSVC 采用的方法似乎是两全其美的方法,因此必须处理符号链接问题,并且总是会生成一个函数符号,无论是否使用都会占用空间。

请任何人都可以建议如何使用 MSVC 为 __forceinline 声明的函数禁用此函数符号生成?

4

2 回答 2

1

我猜“答案”是 MSVC 实现了与链接器的内联;即使 __forceinline 函数的符号是​​在 .obj COFF 对象文件中生成的,它们也不包含在输出 .EXE 或 .DLL 文件中(我检查了 /MAP: map files generated ),我猜是由于隐藏的属性放置在编译器的函数符号。所以我不先调查这个很糟糕 - 对不起。但是对于习惯于 GCC 做事方式的人来说,这会让人感到困惑。

于 2021-06-17T17:00:35.233 回答
0

While I can't answer question at hand (I would not know how to force MSVC to avoid generating a symbol), I would like to point out to several misconceptions in your assumptions regarding uses of __forceinline:

  • "No symbol is generated, so that one has no multiply-defined-symbol or linkage issues" - this does not require __forceinline. A plain inline function is guaranteed to not cause ODR violations, regardless of whether actual symbol was created or not.
  • "The code is only instantiated when used, consuming 0 bytes if not used" - it is not clear what you mean by that. If a function is defined (with a symbol), but not called in the code, the symbol will not make it into final executable, so unused functions will not incur space penalty in executable. It is inlined functions which could lead to code bloat, as each invocation of the function will increase executable size by size of the said function.
  • "No function call / return overhead (the whole point of inline in the first place) - but this saving is somewhat lessened by register save + restore code" - the most benefit of inlined function comes not from the call / return, or register manipulation, but from the fact that such function are transparent for optimization purposes. Compiler does not have to make a lot of assumptions on side effects. In fact, this benefit is there regardless of actual inlining, as it is enough for compiler to know of potential side effects or lack of thereof even if an actual call to generated symbol is made.
于 2021-06-17T16:19:08.083 回答