为什么从C++20模块导出的函数的符号名要包含模块名作为其中的一部分?
在C++20模块中声明的任何函数似乎都会以一种包含模块名的方式被符号化。举例:
export module A;
export void a(int);
int main()
{
a(42);
}
这个 a 在Linux上会被符号化为 _ZW1A1ai,解码后为 a@A(int)。
我理解这对未导出的函数为什么有好处(以便它们可以在同名模块内的多个翻译单元中使用,与外部模块没有冲突),但为什么要对导出函数也进行符号化呢?
此外,似乎可以通过 extern "C++" {...} 禁用这一行为,因此这并非技术上的限制。
看起来这种做法被称为 “强所有权模型”(即在导出和非导出函数中都包含模块名)。
而仅对非导出函数包含模块名的做法被称为 “弱所有权模型”。
解决方案
这是所谓的“强所有权模型”,其中模块对导出符号也具有强所有权。Windows先这样做,GCC和 Clang最终也因为在符号化中加入模块名所带来的一些好处而转向这一做法。
参见:
https://github.com/itanium-cxx-abi/cxx-abi/pull/144
The strong-ownership model is implemented — the symbols of exported entities with named-module attachment are mangled with a module-name component.
https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=73baba1ae1b8f3618c2d3b674117b8a462e0ca76
This implements a strong ownership model, so that exported entities from named modules are mangled to include their module attachment. This gives more informative linker diagnostics and better module isolation. Weak ownership was hoped to allow backwards compatibility with non-modular code, but in practice was very brittle, and C++20 added new semantics for linkage declarations that cover the needed functionality.
https://github.com/llvm/llvm-project/commit/ae4dce8659f313ca2034782583d31993212fa8bd
The hoped-for C++17 compatibility of weak ownership turns out to be fragile