C++ 为什么使用extern struct{}foo会触发带有g++;?

C++ 为什么使用extern struct{}foo会触发带有g++;?,c++,gcc,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 -

我正在构建一个共享库,其中包含如下代码和编译规则:

// 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
此代码编译英特尔(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编译器都会产生警告,指导代码的更正,使其能够链接(至少在这个独立版本中,实际代码将更难确定在何处以及如何修复):

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


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

< p>我正在阅读部分<代码> 3.5代码>,并且假设我读的东西都正确,您的非Type无名称类没有链接,因此不能称为“代码> ExtNe< /Calp> 让我们快速回顾一下:

第一款和第二款是定义和序言

/3
有各种各样的原因,可能是内部链接。它们似乎都不适用(静态、const/constexpr、匿名联合)

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

/5
类作用域和类型定义作用域不适用的内容

/6
阻止不适用的范围项

/7
更多块范围项

/8
啊,我们开始了
这些规则中未包含的名称没有链接….

所以在我看来,链接器只是变得混乱了,因为你试图
extern
引用没有链接的东西。虽然错误消息看起来不好/措词不当,但它发出错误似乎没有问题。

也许这会有所帮助:。如果没有,您可以将其添加到链接列表:)
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 ;