c++ - extern const 链接规范似乎被 G++ 忽略

标签 c++ linker g++ name-mangling

我有一种情况是使用 C++ 编译器构建 C 代码库,与此类似:

lib.h

extern int const values[2] = {1, 2};

lib.c

#include "lib.h"

ma​​in.c

#include <iostream>

extern int const values[2];

int main() {
    std::cout << values[0] << ":" << values[1] << std::endl;
}

由于 C++03 Standard Annex C Compatibility C.1.2 Clause 3 中指出的某些内容,我不得不添加 extern . (使用 -fpermissive 编译会将其隐藏起来。)

顺便说一句,values 在 objdump 中的显示方式与 extern 之前的区别如下:

$ objdump -t lib.o | grep values
0000000000000000 l     O .rodata    0000000000000008 _ZL6values

$ objdump -t main.o | grep values
0000000000000000         *UND*  0000000000000000 values

...然后添加之后是这样的:

$ objdump -t lib.o | grep values
0000000000000000 g     O .rodata    0000000000000008 values

$ objdump -t main.o | grep values
0000000000000000         *UND*  0000000000000000 values

因此名称重整被删除了,我们看到“L”变成了“G”,并且链接器不会提示 values 未定义。


现在想象同样的情况,有两个非常相似的文件,以相同的方式修改:

tmp-exttypes.h

extern const REBYTE Reb_To_RXT[REB_MAX] = { /* bunch of stuff */ };

a-lib.c

extern const REBYTE Reb_To_RXT[REB_MAX];

这是项目中仅有的两个 Reb_To_RXT 定义,构建干净。但它没有链接,当我 objdump 只有两个提到它的文件时,我得到:

$ objdump -t a-lib.o | grep Reb_To_RXT
00000000         *UND*  00000000 Reb_To_RXT

$ objdump -t f-extension.o | grep Reb_To_RXT
00000080 l     O .rodata    00000038 _ZL10Reb_To_RXT

它说 L,它的名字被破坏了。这并没有让这个简单得多的例子开心。但是我想知道在每次出现时外部如何发生这种情况。我是否正确地相信这是确凿的证据……通常不应该发生仅声明为外部的东西在任何地方都不应该有本地链接吗?

最佳答案

我无法理解你的问题。

但是……

extern int const values[2] = {1, 2};

在头文件中,如果该头文件包含在多个翻译单元中,则您有 UB。很可能但不一定会出现链接错误。

一个解决方案:在头部声明数组,比如

extern int const values[2];

但在实现文件中定义它(使用初始化程序)。

另一种解决方案是使用模板技巧或内联函数技巧在头文件中定义数组。

内联函数技巧:

typedef int const Values[2];

inline Values& valuesRef()
{
    static Values   theValues = {1, 2};
    return theValues;
}

static Values& values = valuesRef();

关于c++ - extern const 链接规范似乎被 G++ 忽略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13908376/

相关文章:

c++ - 链接器错误:未定义对 Class::enum 的引用

xcode - 使用XCode增加堆栈大小

C++ 确定外部类指针的最佳方式

c++ - 有效地从缓冲区读取值

c++ - 如何实现 Cloneable 类?

c - 如何在一个文件中定义变量并在另一个文件中使用它

windows - MinGW/MinGW64 链接和依赖于 `msvcrt.dll`

c++ - 为什么重新抛出异常会丢弃 'what()' 给出的信息?

c++ - SFML:dyld:库未加载错误,即使库路径已更新

c++ - 每次运行时计算不同的数字