首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用静态向量时_Orphan_range崩溃

使用静态向量时_Orphan_range崩溃
EN

Stack Overflow用户
提问于 2020-05-14 23:49:12
回答 1查看 1.1K关注 0票数 3

在我的项目中,我使用静态对象的构造函数收集指针,就像注册方法一样。很简单,没有魔法。但是在开始的时候,我经历了一次车祸,我无法解释这里发生了什么。这种崩溃在使用MSVC或Clang的Windows上是可重复的,它们都使用MSVC报头。给出了下面的简单示例。有人能告诉我为什么这会引起问题吗?

在Linux上的GCC和Clang中,这段代码似乎工作得很好:

https://gcc.godbolt.org/z/vSKdpW

bar.cpp

代码语言:javascript
复制
static int bar = 1;

static Registration abc(&bar);

foo.cpp

代码语言:javascript
复制
static std::vector<void*> registrations;

void add_to_array(void* p)
{
    registrations.push_back(p);
}

foo.h

代码语言:javascript
复制
class Registration
{
public:
    Registration(void* op)
    {
        add_to_array(op);
    }
};

在以下崩溃中执行结果(_Pnext为0x8)。

代码语言:javascript
复制
void _Orphan_range(pointer _First, pointer _Last) const { // orphan iterators within specified (inclusive) range
#if _ITERATOR_DEBUG_LEVEL == 2
    _Lockit _Lock(_LOCK_DEBUG);

    _Iterator_base12** _Pnext = &_Mypair._Myval2._Myproxy->_Myfirstiter;
    while (*_Pnext) {    <=======================   **_Pnext** was 0x8.

有人知道为什么不能使用静态向量来简单地收集指向对象的指针吗?foo.cpp是唯一使用push_back的向量的文件。数组不会在其他地方被修改。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-27 03:58:08

在使用VS2019运行时调试了类似的问题之后,我将继续说,这几乎可以肯定是由零初始化(但不是构造)向量造成的。

在我的例子中,法医看起来是这样的:_Pnext的值是0x8,因为_Myproxy是空的。当_ITERATOR_DEBUG_LEVEL设置为2(即:在调试概要文件中)时,_Myproxy将被取消引用,从而导致此崩溃,但是发行版不会崩溃,因为该代码被完全跳过。

现在,查看MSVC142 142/ is 2019的向量实现,您将看到每个构造函数都调用_Alloc_proxy,这就是为_Myproxy分配一些内存并分配值的方法。因此,如果已经调用了构造函数,则必须有一个非空_Myproxy

C++中的静态初始化分两个步骤进行:零初始化,然后以任意链接器确定的顺序进行静态初始化。看起来,按照结束的顺序,foo.cpp的Registration在Bar.cpp的registrations向量之前被构造,实际上是在零初始化(但不是构造)向量上调用push_back

因此,正如注释所建议的那样,您肯定应该重新安排静态初始化,以便在使用之前正确地构造向量。

(在我的例子中,我为包含向量的结构分配内存,但没有在该内存上调用placement operator new。对于任何像我一样发现这个问题的人,都要寻找零向量的任何来源,而不是构造向量。)

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61809337

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档