Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ ASan:heap use after free after vector.emplace(push)\u返回递归函数 #包括 结构节点; std::向量堆; 结构节点{ int x,c; 显式节点(intx):x(x),c(0){ 无效更新(){ 如果(x>0){ 如果(c==0){ c=heap.size(); 堆。向后放置(x/2); } 堆[c]。更新(); } } }; int main(){ 堆。向后放置(100); heap.back().update(); }_C++_Vector_Address Sanitizer - Fatal编程技术网

C++ ASan:heap use after free after vector.emplace(push)\u返回递归函数 #包括 结构节点; std::向量堆; 结构节点{ int x,c; 显式节点(intx):x(x),c(0){ 无效更新(){ 如果(x>0){ 如果(c==0){ c=heap.size(); 堆。向后放置(x/2); } 堆[c]。更新(); } } }; int main(){ 堆。向后放置(100); heap.back().update(); }

C++ ASan:heap use after free after vector.emplace(push)\u返回递归函数 #包括 结构节点; std::向量堆; 结构节点{ int x,c; 显式节点(intx):x(x),c(0){ 无效更新(){ 如果(x>0){ 如果(c==0){ c=heap.size(); 堆。向后放置(x/2); } 堆[c]。更新(); } } }; int main(){ 堆。向后放置(100); heap.back().update(); },c++,vector,address-sanitizer,C++,Vector,Address Sanitizer,考虑上面的代码。当使用g++-fsanize=address(gcc版本10.2.0(Ubuntu 10.2.0-5ubuntu1~20.04))编译并运行时,我得到了AddressSanitizer:heap-use-after-free。在谷歌搜索之后,当我试图访问之前已释放的指针时,似乎会发生此错误。检查ASan的输出显示vector.emplace_back释放了该对象。我相信这是向量自身大小调整的结果,这得到了heap.reserve(1000)使代码运行良好这一事实的支持 然后,我试

考虑上面的代码。当使用
g++-fsanize=address
gcc版本10.2.0(Ubuntu 10.2.0-5ubuntu1~20.04)
)编译并运行时,我得到了
AddressSanitizer:heap-use-after-free
。在谷歌搜索之后,当我试图访问之前已释放的指针时,似乎会发生此错误。检查ASan的输出显示vector.emplace_back释放了该对象。我相信这是向量自身大小调整的结果,这得到了
heap.reserve(1000)
使代码运行良好这一事实的支持

然后,我试着用推回代替定位推回,产生了类似的结果。但是,用循环替换递归效果很好

intmain(){
堆。向后放置(100);
int-prevc=0;
while(true){
intx=heap[prevc].x,c=0;
如果(x>0){
如果(c==0){
c=heap.size();
堆。向后放置(x/2);
}
prevc=c;
}否则{
打破
}
}
}
进一步检查后,似乎在第一次调用
update()
后引发了异常。此外,访问
堆[0]
堆[1]
也可以,但访问
堆[c]
失败


现在我很困惑。我找不到任何未定义的行为,也看不到向量内部大小调整导致我无法访问元素的任何原因。此外,我不确定为什么仅使用递归会失败。我做错了什么?

正如user4581301在评论中指出的,问题实际上不是访问向量中的元素,而是访问
c
,这会失败,因为
已被
堆大小调整删除

在我的特殊情况下,我想写一个没有指针的二叉树,所以递归是必要的。具有讽刺意味的是,这背后的理由是为了避免指针陷阱,但结果适得其反。为了将来参考,我找到了四种可能的解决方案:

  • heap.reserve()
  • 使用数组和指向最后一个元素索引的指针模拟向量(基本上是选项1,但可能更快)
  • 添加类似于
    Node self=*this的内容并通过
    self
    访问所有属性。注意:执行
    Node*self=this不起作用,因为
    self
    将与
    一起失效
  • 只要使用指针;它们的存在是有原因的

  • 正如user4581301在评论中指出的,问题实际上不是访问向量中的元素,而是访问
    c
    ,这会失败,因为
    已被
    堆大小调整删除

    在我的特殊情况下,我想写一个没有指针的二叉树,所以递归是必要的。具有讽刺意味的是,这背后的理由是为了避免指针陷阱,但结果适得其反。为了将来参考,我找到了四种可能的解决方案:

  • heap.reserve()
  • 使用数组和指向最后一个元素索引的指针模拟向量(基本上是选项1,但可能更快)
  • 添加类似于
    Node self=*this的内容并通过
    self
    访问所有属性。注意:执行
    Node*self=this不起作用,因为
    self
    将与
    一起失效
  • 只要使用指针;它们的存在是有原因的

  • 将析构函数添加到
    节点
    ,该节点在调用时打印(可能与
    c
    一起)。你会惊讶的。难道不是
    vector
    调整了一个?方便的读数:@StephenNewell在析构函数中打印
    x
    时,只打印100个。我相信异常是在第一次调用
    update()
    之后引发的。我会将此内容与更多信息一起编辑到问题中。当您在
    heap
    中的节点上调用
    update
    时,请记住
    this
    指的是
    heap
    中的节点,当
    heap.emplace\u back(x/2)时调整堆的大小,
    这有点像。这意味着在
    堆[c].update()中使用
    c
    将是一次相当冒险的经历。在
    节点
    中添加一个析构函数,在调用它时打印(可能与
    c
    一起)。你会惊讶的。难道不是
    vector
    调整了一个?方便的读数:@StephenNewell在析构函数中打印
    x
    时,只打印100个。我相信异常是在第一次调用
    update()
    之后引发的。我会将此内容与更多信息一起编辑到问题中。当您在
    heap
    中的节点上调用
    update
    时,请记住
    this
    指的是
    heap
    中的节点,当
    heap.emplace\u back(x/2)时调整堆的大小,
    这有点像。这意味着在
    堆[c].update()中使用
    c
    将是一次相当大的冒险。请注意第3点。我不确定这是否100%合法。请记住,该程序仍在包含无效
    this
    的方法中。快速查看该标准没有发现任何明确说明该标准是否有效的内容,但您已保证不会使用该标准,并且在实践中应该是安全的。关于第3点的说明。我不确定这是否100%合法。请记住,该程序仍在具有无效