c++ - 为什么使用 extern struct {} foo,会触发无效的 fPIC required 错误消息?

标签 c++ gcc

我正在构建一个共享库,它具有如下所示的相应代码和编译规则:

// x.C
struct {
   short len;
   char s[32700];
   } foo;

// u.C
extern struct {
   short len;
   char s[32700];
   } foo;

void blah(void)
{
   foo.s[0] = 0 ;
}

$CXX -c x.C -fPIC
$CXX -c u.C -fPIC
$CXX -shared -o x.so.1 -Wl,-soname,x.so.1 x.o u.o

此代码使用 intel (v13-v16) 编译器和 clang 编译器 (v3.6) 进行编译和链接,但使用 g++(版本 4.9.2)时出现链接错误:

u.o: relocation R_X86_64_PC32 against undefined symbol `foo' can not be used when making a shared object; recompile with -fPIC

这里关于-fPIC 的链接错误显然是错误的,因为代码是用fPIC 编译的。我还在 objdump -x 输出中看到符号的重定位记录:

RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE
0000000000000006 R_X86_64_PC32     foo-0x0000000000000003

clang 和 gcc 编译器都会产生警告,指导更正允许它链接的代码(至少这个独立版本,实际代码将更难弄清楚在哪里以及如何修复):

u.C:5:10: warning: anonymous type with no linkage used to declare variable '<anonymous struct> foo' with linkage
        } foo;
          ^

果然我可以通过删除匿名结构来解决这个问题:

// u.h
struct fooT {
   short len;
   char s[32700];
   } ;

extern fooT foo ;

// u.C
#include "u.h"

void blah(void)
{
   foo.s[0] = 0 ;
}

// x.C
#include "u.h"

struct fooT foo ;

因此,虽然我有解决办法,但我想了解这里发生了什么。我看到一些有类似链接错误的问题:

其中一些表明这可能与符号可见性有关。 gcc 是否将此符号标记为隐藏以触发最终的链接错误? g++、clang++ 或 intel 编译器中的哪一个在这里表现得正确或不正确,或者这个构造是无效的并且完全不可移植?如果这是无效代码,它违反了 C++ 标准的哪一部分?

最佳答案

我正在阅读 3.5 部分,假设我没看错,您的非 typedef 未命名类没有链接,因此不能称为 extern

让我们快速回顾一下:

第一段和第二段是定义和序言。

/3 有多种原因表明它是内部链接。它们似乎都不适用(静态、const/constexpr、匿名 union )。

/4 都与未命名的命名空间有关

/5 类作用域和 typedef 作用域不适用。

/6 阻止不适用的范围项目。

/7 更多 block 范围项。

/8 啊,我们开始吧 这些规则未涵盖的名称没有链接....

所以在我看来,链接器只是感到困惑,因为您正试图 extern 引用没有链接的内容。虽然错误消息看起来很糟糕/措辞不当,但它似乎可以发出错误。

关于c++ - 为什么使用 extern struct {} foo,会触发无效的 fPIC required 错误消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30039601/

相关文章:

c++ - 如果不需要,从库中发出信息而无需运行时成本

c++ - 确保相机位置始终位于屏幕中心?

gcc - 为什么 FFmpeg 没有经过编译器优化?

c++ - 模板类实例化的多重继承以及对成员函数的访问

将 char 数组转换为一个 int

c++ - 无法同时编译ncurses和字符串

C++ 字符串警告

c++ - ** 和 * [] 一样吗?

c - 如何列出目标文件中静态声明的大小?

XCode 上 cin 和 cout 的 C++ 执行顺序无效