为何用__declspec(dllexport)导出类时会连带导出未标记的helper符号?
为何内联调用后
detail::helper符号仍会生成? 示例源码
namespace detail { inline int helper() { return 1; } } struct __declspec(dllexport) Foo { int fun() { return 2 * detail::helper(); }; };
编译行为说明
未添加__declspec(dllexport)时,编译器不会生成任何目标代码;添加该导出标记后,生成的汇编代码如下:
int detail::helper(void) PROC ; detail::helper, COMDAT mov eax, 1 ret 0 int detail::helper(void) ENDP ; detail::helper this$ = 8 int Foo::fun(void) PROC ; Foo::fun, COMDAT mov eax, 2 ret 0 int Foo::fun(void) ENDP ; Foo::fun
核心问题
既然Foo::fun的汇编已经直接内联了helper()的计算逻辑(直接返回2),为何detail::helper的函数符号仍会出现在汇编输出中?
解答
这是Windows平台__declspec(dllexport)导出机制的特性导致的:
- 当标记类
Foo为dllexport时,编译器会强制导出该类相关的所有依赖符号,哪怕这些符号已经被内联优化。这是为了保证动态链接库的外部调用者不会遇到符号解析失败的问题,即使外部模块可能尝试直接引用这些依赖实体。 detail::helper是inline函数,虽然在Foo::fun里被内联展开,但因为Foo被标记为需要导出,编译器必须为helper生成一个外部可见的实体实例——C++标准允许inline函数有多份定义,但导出时需要一个唯一的、可被外部模块引用的版本,所以会显式生成该函数的汇编代码。- 简单说,
dllexport会让编译器放弃部分内联优化的符号消除逻辑,优先保证所有依赖符号的导出可见性。
内容的提问来源于stack exchange,提问作者Enlico
相关产品推荐
相关产品推荐

