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

时间:2018-10-15 04:04:54

标签: c++ exception inline c++17

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

main.cpp

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

int main()
{
    return 0;
}

header1.h中:

#include <list>

struct Boo
{
    static inline std::list<int> mylist;
};

anotherCPP.cpp

#include "Header1.h"

程序退出main()时,它会破坏所有静态对象并引发异常。

如果这不会崩溃,则可能是在您的系统上,编译器/链接器优化了一些代码,因此您可以尝试使 main.cpp anotherCPP.cpp 起作用的东西。在 otherCPP.cpp 中:

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

void aFunction()
{
    std::cout << Boo::mylist.size();
}

并创建main.cpp:

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

void aFunction();

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

    return 0;
}

当程序退出时,在清除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);
}

仅当我在类中声明了静态内联std :: list mylist时,才会发生这种情况。如果我在类中将其声明为 static std :: list mylist ,然后在一个.cpp中分别将其定义为 std :: list Boo :: mylist; < / em>正常。当我声明std :: list静态内联并且在两个.cpp文件中包含该类的标头时,就会出现此问题。

在我的项目中,我从上面逐步完成了std :: list清除循环,我记下了“ this”指针地址。我逐步完成了循环,因为它释放了列表中的节点。然后返回免费的其他std :: lists,包括在std :: unordered_map中(因为它们从外观上也使用std :: lists)。最后,当抛出读取访问异常并且 _Pnode 是无效的指针地址时,我注意到在清除 std :: list时,“ this”指针地址与“ this”指针地址相同 mylist ,这使我认为它试图将其删除两次,并且可能是它崩溃的原因。

我希望有人能重现此内容,如果是错误或我做错了什么,我不确定这是什么。同样,这对我来说是32位和64位的,但仅在调试模式下会发生,因为我提供的节点释放循环在宏下:

#if _ITERATOR_DEBUG_LEVEL == 2

1 个答案:

答案 0 :(得分:2)

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

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

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