【问题标题】:Deallocating a <vector <vector<DataClass>> as a class member将 <vector <vector<DataClass>> 重新分配为类成员
【发布时间】:2012-10-19 05:02:00
【问题描述】:

我有一个类,我们称它为 Builder。它有一个私有成员声明为

vector< vector< Node >> buffers; // Node is a pure data class.

在这个 Builder 类构造函数中,我这样做:

buffers = vector< vector< Node >>(amount);

其中“数量”仅在运行时才知道。

在构建器类的生命周期中,会在缓冲区成员上调用几个操作。我正在使用的唯一操作是:

buffers[i].push_back(Node());
buffers[i].clear();

我只是在这里添加算法的肉供参考:

// REFINE BUFFERS
// check all levels (bottom up) and group 8 nodes on a higher level
for(int d = maxdepth; d >= 0; d--){
    if(buffers[d].size() == 8){ // if we have 8 nodes
        if(isBufferEmpty(buffers[d])){ 
            buffers[d-1].push_back(Node()); // push back NULL to represent 8 empty nodes
        } else { 
            buffers[d-1].push_back(groupNodes(octree, buffers[d])); // push back parent node
        }
        buffers[d].clear(); // clear the 8 nodes on this level
    } else {
        break; // break the for loop: no upper levels will need changing
    }
}

当 Builder 类对象超出范围时,它会被销毁,它的类成员也会随之销毁。当我在VS2010调试模式下,没有问题。在发布模式下,我收到以下错误:“Windows 已触发断点”。

问题在于 STL:vector 规范的这一部分,在 _Destroy 调用处。

void _Tidy()
    {   // free all storage
    if (this->_Myfirst != 0)
        {   // something to free, destroy and deallocate it
        this->_Orphan_all();
        _Destroy(this->_Myfirst, this->_Mylast);
        this->_Alval.deallocate(this->_Myfirst,
            this->_Myend - this->_Myfirst);
        }
    this->_Myfirst = 0;
    this->_Mylast = 0;
    this->_Myend = 0;
    }

查看调试器,我可以看到 _Mylast 的值不正确(0x000000000000),这可能是导致此取消分配失败的原因。当我尝试在最后执行 buffers.clear() 时,我得到了相同的结果。 (buffers[i].clear() 工作正常)。另外,当我点击“继续”时,我的程序也可以正常运行。

我的算法运行后有一些输出。您看到的是各个向量中的元素数量,以及 buffers[i].begin() 和 buffers[i].end() 指向的地址。 “主缓冲区”是指调用 buffers.begin() 和 buffers.end() 时得到的值。

  Main Buffer begin: 0000000002068050
  Main Buffer end  : 0000000002068130
  buffers[0] : 0 elements, 0000000002068160 - 0000000002068160
  buffers[1] : 0 elements, 0000000002070080 - 0000000002070080
  buffers[2] : 0 elements, 0000000002068E70 - 0000000002068E70
  buffers[3] : 0 elements, 0000000001F71810 - 0000000001F71810
  buffers[4] : 0 elements, 0000000002068BB0 - 0000000002068BB0
  buffers[5] : 0 elements, 00000000020688F0 - 00000000020688F0
  buffers[6] : 0 elements, 0000000002068370 - 0000000002068370

现在我的问题是,我怎么会损坏 _Mylast? (无论如何,我已经破坏了堆)

当我将以前只是在全局范围内定义的函数的算法移动到一个类中时,这个问题才开始出现。我怀疑这与 C++ 如何将向量作为类成员处理有关。

我的构建器类应该能够设置一定数量的缓冲区(向量内容),并且只要节点还活着,就可以将节点弹出并推送到这些缓冲区中。这就是我想要实现的目标。

【问题讨论】:

  • 您可能正在访问超出范围的数组。尝试使用at() 而不是operator[],然后在确定它正常工作后将它们全部切换回来。
  • 试过了,没什么区别。
  • 更新:我在程序的完全不同部分写入未分配的内存位 - 将第一个答案标记为正确,因为这是一个类似的问题。

标签: c++ vector destructor


【解决方案1】:

即使d 为零,您也会写信给buffers[d-1]。这可能是你的问题吗?有时直到稍后才会检测到越界错误(例如当向量被释放时)。

【讨论】:

  • 如果这不是问题的原因,那么它似乎是一个问题。
  • 为此添加了额外的检查,但这并没有解决我的问题。
【解决方案2】:

确保您的Node 对象可以被复制并随后被正确销毁;一个非常常见的错误是让您包含的对象(在本例中为Node)在其析构函数中执行某些操作,这取决于它拥有其所有底层数据的唯一副本。您可能希望缓冲区存储 shared_ptr&lt;Node&gt; 以防止复制开销,或者至少确保您已实现 Node::Node(const Node &amp;)Node::operator=(const Node &amp;) 以确保您的复制语义正确(以及更改任何原始Node 中的指针也是 shared_ptr)。

您可能还想阅读RAII principles,因为这将有助于防止以后出现这些错误。

【讨论】:

  • 从输出中可以看出,最终要清除的缓冲区不再包含任何 Node 对象...
  • @JeroenBaert 没关系。如果你在做一个双重释放,你的堆就搞砸了。
猜你喜欢
  • 2012-01-23
  • 1970-01-01
  • 2019-06-09
  • 1970-01-01
  • 1970-01-01
  • 2016-12-07
  • 1970-01-01
  • 2014-02-02
  • 1970-01-01
相关资源
最近更新 更多