在Windows上,使用link.exe和lld-link.exe,Clang/LLVM 7和8会多次初始化内联静态数据成员。

12

在Windows环境下,Clang/LLVM 7和8对inline静态数据成员进行了一次TU初始化。就我理解的C++17而言,这是不正确的。

虽然inline变量可以在多个TU中定义,但编译器和/或链接器必须确保它在程序中只存在一次,因此仅被初始化一次

以下小程序展示了Clang/LLVM的具体操作(在Visual Studio 2017和2019 RC中测试了LLVM Compiler Toolchain扩展):

// header.h

#include <iostream>

struct A
{
  A()      { std::cout << "ctor " << this << std::endl; }
  ~A()     { std::cout << "dtor " << this << std::endl; }
  void f() { std::cout << "f " << this << std::endl;  }
};

struct S
{
  inline static A a; // C++17 inline variable, thus also a definition 
};

// TU1.cpp

->

// TU1.cpp

#include "header.h"

int main()
{
  S::a.f();
}

// TU2.cpp

#include "header.h"
#include "header.h"

// TU4.cpp

// TU4.cpp 是一个代码文件的文件名。
#include "header.h"

这个程序会输出:

ctor 010D4020
ctor 010D4020
ctor 010D4020
ctor 010D4020
f 010D4020
dtor 010D4020
dtor 010D4020
dtor 010D4020
dtor 010D4020

这意味着A类的唯一对象将有四个初始化(实际上是每个翻译单元一个),而不是像C++17要求的仅有一个

程序应该输出:

ctor 010D4020
f 010D4020
dtor 010D4020

顺便说一下,这就是MSVC的作用。

这是clang/LLVM中的一个bug,对吧?


你在使用Clang的哪些编译选项? - Serge Ballesta
4
你之前提出的问题和现在这个问题有什么不同之处? - xskxzr
@xskxzr 另一个问题涉及 lld-link.exe,而这个问题涉及 link.exe。 - x y
@SergeBallesta -Xclang -std=c++17 -Xclang -flto -Xclang -O3 - x y
去掉-flto和-O3都没有改变任何东西。因此,它不取决于这两个选项。-Xclang对于clang的cl.exe是必需的(我正在使用Visual Studio 2017),因为这些选项必须直接传递给clang。否则,它们将未被使用(在-O3的情况下)或混淆link.exe(在-flto的情况下)。 - x y
显示剩余3条评论
2个回答

7
inline 关键字的主要特点是它以两种方式修改了 ODR 规则:
  1. 允许多个定义(有一些限制)存在

  2. 生成的对象被“折叠”成单个实例

    具有外部链接的内联函数或变量在所有翻译单位中地址相同。

C++17 中唯一的补充是它还允许将静态数据成员声明为定义。就是这样。
一个static数据成员仍然具有相同的外部链接(在您的情况下),存储期限生命周期,对于所有实际目的,它的工作方式就像全局定义的变量一样。请参见[class.static.data]/6

静态数据成员的初始化和销毁与非本地变量完全相同

这基本上意味着它应该与以下内容相同:
struct A
{
  A()      { std::cout << "ctor "; }
  ~A()     { std::cout << "dtor "; }
};

A a; // in one of the TU's

extern A a; // in all other TU's

结论:

这是Clang中的一个bug。静态变量S::a必须被初始化并且只能被销毁一次。


谢谢,这正是我所怀疑的。我会在llvm.org上提交一个错误报告。 - x y
我在2018年6月报告了这个问题,针对的是6.0.0版本。但即使在全新的8.0.0版本中,这个问题仍然存在。有人知道为什么还没有修复吗? - x y
Clang 13中是否仍存在该漏洞?我认为是的。 - MKFein

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接