【问题标题】:0xfeeefeee segmentation fault, but simple allocation change?0xfeeefeee 分段错误,但简单的分配更改?
【发布时间】:2014-05-08 20:13:55
【问题描述】:

我正在实现一个 Barnes-Hut 模拟程序,并且有这个简短的 sn-p 代码:

BhTree *BhTree::make() {
    return new BhTree();
}

代码的其余部分(大量)然后工作得很好。创建的节点在程序生命周期内从不删除。利用这个事实,我想通过以下方式优化分配:

vector<BhTree> mSpace;
BhTree *BhTree::make() {
    mSpace.push_back(BhTree());
    return &mSpace[mSpace.size()-1];
}

这会导致代码中不相关的部分出现可怕的分段错误。有趣的是,在一个递归函数中,this 突然变成了0xfeeefeee,这是用于释放堆内存的 Microsoft 代码。

任何人都可以立即看出问题所在吗?向量mSpace从不在其他地方访问。

【问题讨论】:

  • 你在哪里定义mSpaceBhtree 的静态成员?全局变量?
  • 你也可以返回一个索引,并通过mSpace中的索引引用BhTree

标签: c++ segmentation-fault fault


【解决方案1】:

随着std::vector 的增长,它将重新分配内存来存储其内容,并使您之前发出的所有指针失效。

【讨论】:

  • 当然!典型的脑残思维错误。然后我需要创建一个大的初始缓冲区。
  • @bombax:您可以改用std::deque,因为它不会在指针增长时(从任一端)无效。
  • 谢谢!虽然我有点担心没有 reserve 函数,因为我知道从一开始就需要分配多少。
  • @bombax deque 没有它,因为它比vector 具有更好的(理论上的)插入时间复杂度。
【解决方案2】:

您正在返回一个指向由向量管理的对象的指针:

&mSpace[mSpace.size()-1];

一旦向量扩展其内部缓冲区并将对象复制到新位置,地址就会失效。

您有 3 个选项:

  • 更改所有代码以通过值/引用而不是指针传递对象
  • 改为使用矢量存储 std::shared_ptr&lt;Bhtree&gt;(如果您的编译器支持 C++ 11)。
  • 使矢量存储Bhtree* 并确保delete 每个元素

第二个变体如下所示:

std::vector<std::shared_ptr<Bhtree>> mSpace;

BhTree *BhTree::make() {
    mSpace.push_back(std::make_shared<BhTree>());
    return mSpace.back().get();
}

【讨论】:

  • 谢谢!我认为我将采用的解决方案是制作一个足够大的初始缓冲区。
  • @bombax 只会推迟问题,并且仍然容易受到未定义行为的影响。我强烈反对这样做。为什么不选择第二个或第三个选项?
  • 重点是减少对new 的调用次数,因为我宁愿分配一大块并使用它。但我明白你的意思。
【解决方案3】:

mSpace.push_back() 可以在确定向量内部数组空间不足时调整其大小。发生这种情况时,向量的内部数组变得无效,并且指向向量元素的旧指针也无效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-16
    • 2022-01-07
    • 1970-01-01
    • 2021-09-19
    • 2011-05-12
    相关资源
    最近更新 更多