为什么优化标志会导致某些模板函数的链接器错误?
我遇到一个问题,应用程序在关闭所有优化的情况下在调试模式下编译良好。 但是当我编译发布时,它会打印出未解决的链接错误。
有问题的功能如下:
template <typename T>
T & Block::val(size_t offset)
{
return *(reinterpret_cast<T*>(_data + offset));
}
template <typename T>
const T & Block::val(size_t offset) const
{
return *(reinterpret_cast<T*>(_data + offset));
}
我得到的错误都看起来像:
undefined reference to `unsigned long long& Block::val<unsigned long long>(unsigned long)'
可能是什么原因导致的?
I have a problem where an app compiles fine in debug mode with all optimization turned off.
But the moment I compile for release it prints out unresolved link errors.
The functions in question are the following:
template <typename T>
T & Block::val(size_t offset)
{
return *(reinterpret_cast<T*>(_data + offset));
}
template <typename T>
const T & Block::val(size_t offset) const
{
return *(reinterpret_cast<T*>(_data + offset));
}
And the errors I'm getting all look like:
undefined reference to `unsigned long long& Block::val<unsigned long long>(unsigned long)'
What might be causing this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您通常不会将模板实现放入 .cpp 中,而是放入 .h 中包含的 .h 或 .inl 中,这可能是 .o 的调试版本对其导出的符号更加自由。
在 .o 的调试和发布版本上运行 nm 并比较符号。
由于单一定义规则,模板在链接器中并不常见。当涉及到模板时,主体位于标题中,这会导致多个等效定义,每个翻译单元一个。链接器让它们全部保留到最后一刻,它任意选择一个并丢弃其他。
我在这里猜测,但我怀疑当您在没有优化的情况下进行编译时,主体会被视为正常,但是当进行优化时,编译器会花费一些额外的努力来确定该主体在其他翻译单元中不可见
查找外部模板。
You normally wouldn't put template implementations in a .cpp but rather a .h or .inl which is included from a .h, it could be that the debug build of the .o is more liberal with the symbols it exports.
Run
nm
on the debug and release builds of the .o and diff the symbols.Templates are unusual in linkers because of the One Definition Rule. When it comes to templates, where the body is in the header, this results in multiple equivalent definitions, one for each translation unit. The linker lets them all be until the last moment, where it selects one arbitrarily and discards the others.
I am guessing here, but I suspect that when you compile without optimisations the body is treated like normal, but when optimisations are on the compiler spends a bit of extra effort determining that this body is not visible in other translation units and declines to export it.
Look up extern templates.
这一点也不奇怪。函数模板定义从第一天起就属于头文件。不要将它们放入源中。如果这样做,编译器将在实例化时看不到它们。
This is not odd in the slightest. Function template definitions belong to header files since day one. Do not put them in sources. If you do, the compiler won't see them at instantiation time.