【问题标题】:Clang/LLVM 7 and 8 on Windows initialize inline static data member multiple times (with both link.exe and lld-link.exe)Windows 上的 Clang/LLVM 7 和 8 多次初始化内联静态数据成员(同时使用 link.exe 和 lld-link.exe)
【发布时间】:2018-06-22 07:01:58
【问题描述】:

Windows 上的 Clang/LLVM 7 和 8 初始化一个内联静态数据成员每个 TU 一次。据我了解 C++17 这是不正确的。

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

以下小程序展示了使用 Clang/LLVM 会发生什么(在 Visual Studio 2017 和 2019 RC 中测试,带有 LLVM 编译器工具链扩展):

// 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

#include "header.h"

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

// TU2.cpp

#include "header.h"

// TU3.cpp

#include "header.h"

// TU4.cpp

#include "header.h"

这个程序打印:

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

这是针对 A 的唯一一个对象的 四个 初始化(实际上每个 TU 一个),而不是正好一个(如 C++17 要求的那样)。 p>

程序应该打印:

ctor 010D4020
f 010D4020
dtor 010D4020

顺便说一句,这就是 MSVC 所做的。

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

【问题讨论】:

  • Clang 使用了哪些编译选项?
  • 和你之前问的the question有什么区别?
  • @xskxzr 另一个问题是指lld-link.exe,这个是link.exe。
  • @SergeBallesta -Xclang -std=c++17 -Xclang -flto -Xclang -O3
  • 是否取决于优化选项?如果你删除-flto-Xclang 的含义是什么?当您使用-std=c++17 时,我真的认为这是一个 Clang 问题,但我认为您只需要使用相关选项即可填写错误报告。

标签: c++ clang c++17 llvm-clang


【解决方案1】:

inline 关键字的主要特点是它以两种方式修改 ODR 规则:

  1. 多个定义(有一些限制)是allowed

  2. 生成的对象被“折叠”成single instance

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

在 C++17 中唯一的补充是它还将 allowsstatic 数据成员声明作为定义。就是这样。

static 数据成员仍然具有相同的链接(在您的情况下为 external),storage durationlifetime,并且对于所有实际目的,就像全局定义的变量一样工作. 见[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 中的一个错误。 static S::a 必须初始化并销毁一次。

【讨论】:

  • 谢谢,这就是我的怀疑。我将在 llvm.org 上提交错误报告。
  • 好吧,我在 2018 年 6 月将其报告为 6.0.0 的错误。但即使在全新的 8.0.0 中,它仍然存在。有谁知道为什么这不是固定的?
  • Clang 13 中是否仍然存在该错误?我想是的。
【解决方案2】:

This bug is fixed 在当前基于 SVN r361807 的快照构建中。

【讨论】:

    猜你喜欢
    • 2012-12-28
    • 2019-10-03
    • 1970-01-01
    • 1970-01-01
    • 2019-07-25
    • 1970-01-01
    • 2014-09-01
    • 2020-05-18
    • 1970-01-01
    相关资源
    最近更新 更多