在Visual Studio中使用C++ 17静态内联成员时出现奇怪的行为

Zeb*_*ish 6 c++ inline exception c++17

昨天我问了一个关于这个问题的问题,但是我无法给出一个MVCE.我已经设法通过一个简单的程序重现这一点.问题是在类中使用std :: list作为静态内联声明.Microsoft Visual Studio确实支持这种新的C++ 17功能.截至3月份它有一些错误,但据我所知,它们已被修复.以下是如何解决此问题的说明,这种情况发生在调试模式下.

main.cpp中

#include <iostream>
#include "header1.h"

int main()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

header1.h中:

#include <list>

struct Boo
{
    static inline std::list<int> mylist;
};
Run Code Online (Sandbox Code Playgroud)

另一个CPP.cpp中

#include "Header1.h"
Run Code Online (Sandbox Code Playgroud)

当程序退出main()时,它会销毁所有静态对象并抛出异常.

如果这没有崩溃,可能在你的系统上编译器/链接器优化了一些代码,所以你可以尝试使main.cpp另一个CPP.cpp做一些事情.在另一个CPP.cpp中:

#include <iostream>
#include "Header1.h"

void aFunction()
{
    std::cout << Boo::mylist.size();
}
Run Code Online (Sandbox Code Playgroud)

并使main.cpp:

#include <iostream>
#include "Header1.h"

void aFunction();

int main()
{
    std::cout << Boo::mylist.size();
    afunction();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当程序退出时,我在清除std :: list时会遇到异常.以下是崩溃的Visual Studio调试代码:

for (_Nodeptr _Pnext; _Pnode != this->_Myhead(); _Pnode = _Pnext)
{   // delete an element
    _Pnext = _Pnode->_Next; // Here: Exception thrown: 
                            // read access violation.
                            // _Pnode was 0xFFFFFFFFFFFFFFFF.

    this->_Freenode(_Pnode);
}
Run Code Online (Sandbox Code Playgroud)

只有在类中声明静态内联std :: list <int> mylist时才会发生这种情况.如果我在我的类中将它声明为静态std :: list <int> mylist,然后在一个.cpp中单独定义它作为std :: list <int> Boo :: mylist; 它工作正常.当我声明std :: list static inline并且我在两个.cpp文件中包含该类的头时,会出现此问题.

在我的项目中,我从上面逐步执行了std :: list clear循环,我注意到了"this"指针地址.我逐步完成循环,因为它释放了列表中的节点.然后它回来释放其他std :: lists,包括在std :: unordered_map中(因为它们也使用了std :: lists).最后当抛出读访问异常并且_Pnode是一个无效的指针地址时,我注意到当清除std :: list <int> mylist时,"this"指针地址与"this"指针地址相同,这让我觉得它试图删除它两次,也许是为什么它会崩溃.

我希望有人可以重现这一点,我不确定这是什么,如果它是一个错误或我做错了什么.这也发生在32位和64位,但仅在调试模式下,因为我提供的节点释放循环在宏下:

#if _ITERATOR_DEBUG_LEVEL == 2
Run Code Online (Sandbox Code Playgroud)

P.W*_*P.W 2

此问题已作为错误提交,标题为“调试模式下内联静态数据成员的多重初始化”。

这是在 Visual Studio 2017 版本 15.7 中发现的。

VS 编译器团队已经接受了这一点,并在即将发布的版本中修复了该问题。