内联变量被多次初始化

时间:2018-11-07 19:45:07

标签: c++ visual-studio-2017 c++17

我看到article/%slug% 变量的一些示例在Visual Studio 2017中被初始化(和销毁)了3次。这是链接器的错误吗?还是应该以其他方式发生?

链接器Comdat折叠设置为“关”。

示例代码:

//default us/en/article/%article_name% to article/%article_name%
add_rewrite_rule('^article/([^/]*)?',
                 'index.php?pagename=$matches[1]&article_locale=us&article_language=en&post_type=article-en',
                 'top');

在我的解决方案中,我有两次断言触发(一次构造函数称为3次)。 检查调用堆栈显示所有调用堆栈都是相同的,并且所有调用都来自a()的动态初始化程序。现在,我知道一个事实,因为我只是创建该类来研究此问题,所以该类未在解决方案的其他部分使用。

我使用VS17 15.8.9

更新:此处https://developercommunity.visualstudio.com/content/problem/297876/static-inline-variable-gets-destroyed-multiple-tim.html的错误报告(您可以投票以帮助推送错误修正)

3 个答案:

答案 0 :(得分:6)

这似乎是MSVC错误。我可以使用下面的代码(也可以使用VS2017 15.8.9)重现它。有趣的是,我只能使用Debug版本进行复制。在发布模式下,优化器似乎可以拯救我们。

Common.h

#pragma once

#include <iostream>

class Foo
{
public:
  Foo()
  {
    std::cout << "Constructing a Foo" << std::endl;
  }

  ~Foo()
  {
    std::cout << "Destructing a Foo" << std::endl;
  }
};

inline Foo const Bar;

other.cpp

#include "common.h"

void DoOtherStuff()
{
  std::cout << &Bar << std::endl;
}

main.cpp

#include "common.h"

void DoStuff()
{
  std::cout << &Bar << std::endl;
}

extern void DoOtherStuff();

int main()
{
  DoStuff();
  DoOtherStuff();
}

输出(调试)

Constructing a Foo
Constructing a Foo
00007FF74FD50170
00007FF74FD50170
Destructing a Foo
Destructing a Foo

答案 1 :(得分:4)

我使用MS C ++编译器版本19.16(例如,Visual Studio 15.9.4附带)在调试和发布(/ Ox)模式下均收到该错误。

Inline.Hpp

#include <iostream>  
inline struct Foo  
{ Foo() { std::cout << "Constructing a Foo at " << this << std::endl; } }  
Instance;  

Inline.cpp

#include "Inline.Hpp"  
int main() { return 0; }  

Inline2.cpp

#include "Inline.Hpp"    

编译并链接了inline.cpp和inline2.cpp之后,运行时的输出为:

Constructing a Foo at 00BE4028  
Constructing a Foo at 00BE4028  

编译器和链接器正确地将两个内联定义解析为单个对象,但错误地为每个定义调用了构造函数,而不仅仅是一次。这是一个严重的错误,导致C ++ 17的“内联变量”功能不可用。 “解决方法”是将内联变量视为从19.16版开始仍不受MS C ++支持,即使使用/ std:c ++ 17开关也是如此。

答案 2 :(得分:2)

从今天开始,Visual Studio 2017的版本15.9.24进行了更新,从而解决了该问题。

从发行说明:

修复了C ++编译器错误,可以正确折叠内联变量动态 初始化程序。