C++ 为什么我可以更新boost::fibonacci_堆中弹出的元素?

C++ 为什么我可以更新boost::fibonacci_堆中弹出的元素?,c++,boost,heap,fibonacci-heap,C++,Boost,Heap,Fibonacci Heap,我正在使用boost::fibonacci_堆库实现一个快速行进算法,并且开始使用元素的句柄来操作元素 我已经编写了下面的基本代码,它编译得很好,但我不理解它的行为: 我首先将每个推送元素的句柄存储在一个数组中。然后我从堆中弹出第一个元素,检查堆大小是否减小 但随后我尝试使用其句柄更新弹出的元素的值。这个操作有效(令人惊讶?),并且更新的元素现在位于堆的顶部。但是堆大小保持不变,因为我没有正确地推入新元素 那么,当弹出的元素被更新并返回到堆中时会发生什么呢?堆仍然有效吗 #包括 #包括 使用名称

我正在使用boost::fibonacci_堆库实现一个快速行进算法,并且开始使用元素的句柄来操作元素

我已经编写了下面的基本代码,它编译得很好,但我不理解它的行为:

我首先将每个推送元素的句柄存储在一个数组中。然后我从堆中弹出第一个元素,检查堆大小是否减小

但随后我尝试使用其句柄更新弹出的元素的值。这个操作有效(令人惊讶?),并且更新的元素现在位于堆的顶部。但是堆大小保持不变,因为我没有正确地推入新元素

那么,当弹出的元素被更新并返回到堆中时会发生什么呢?堆仍然有效吗

#包括
#包括
使用名称空间std;
使用名称空间boost::heap;
结构节点
{
整数指数;
双倍时间;
节点(常数int&i,双t):索引(i),时间(t){}
};
结构比较节点
{
布尔运算符()(常数节点&n1,常数节点&n2)常数
{
返回(n1.时间>n2.时间);
}
};
int main()
{
fibonacci_堆<节点,比较>堆;
typedef fibonacci_heap::handle_type handle\u t;
手柄[10];
int n;
双tt[10];
//指定一组任意数字来初始化数组tt:
tt[0]=5.3;
tt[1]=0.25;
tt[2]=3.6;
tt[3]=1.75;
tt[4]=9.1;
tt[5]=2.54;
tt[6]=3.8;
tt[7]=6.1;
tt[8]=1.23;
tt[9]=7.32;
//将tt的值推送到堆中,并跟踪堆中每个元素的句柄:
对于(n=0;n实际上,您正在调用

在valgrindª下运行您的程序:

sehe@desktop:/tmp$ valgrind --db-attach=yes ./test
==14185== Memcheck, a memory error detector
==14185== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==14185== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==14185== Command: ./test
==14185== 
first element in heap is :1 0.25
size of heap is :10
size of heap after pop is :9
first element in heap is now :8 1.23
element index 2 has time :3.6
==14185== Invalid read of size 8
==14185==    at 0x400F21: main (test.cpp:47)
==14185==  Address 0x5aa6d78 is 24 bytes inside a block of size 72 free'd
==14185==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14185==    by 0x402789: __gnu_cxx::new_allocator<boost::heap::detail::marked_heap_node<node> >::deallocate(boost::heap::detail::marked_heap_node<node>*, unsigned long) (new_allocator.h:110)
==14185==    by 0x401D2C: boost::heap::fibonacci_heap<node, boost::heap::compare<compare_node>, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_>::finish_erase_or_pop(boost::heap::detail::marked_heap_node<node>*) (fibonacci_heap.hpp:745)
==14185==    by 0x4015E7: boost::heap::fibonacci_heap<node, boost::heap::compare<compare_node>, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_>::pop() (fibonacci_heap.hpp:398)
==14185==    by 0x400E1C: main (test.cpp:34)
==14185== 
==14185== 
==14185== ---- Attach to debugger ? --- [Return/N/n/Y/y/C/c] ---- 
sehe@desktop:/tmp$valgrind--db attach=yes./test
==14185==Memcheck,内存错误检测器
==14185==2002-2013年版权(C)和GNU GPL'd,朱利安·苏厄德等人。
==14185==使用Valgrind-3.10.0.SVN和LibVEX;使用-h重新运行以获取版权信息
==14185==命令:./test
==14185== 
堆中的第一个元素是:1 0.25
堆的大小为:10
pop后的堆大小为:9
堆中的第一个元素现在是:81.23
元素索引2的时间:3.6
==14185==大小为8的无效读取
==14185==0x400F21:main(test.cpp:47)
==14185==地址0x5aa6d78是大小为72 free'd的块中的24字节
==14185==at 0x4C2C2BC:operator delete(void*)(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)
==14185==by 0x402789:u gnu_cxx::新的_分配器::解除分配(boost::heap::deal::marked_heap_node*,unsigned long)(新的_分配器.h:110)
==14185==by 0x401D2C:boost::heap::fibonacci_heap::finish_erase_或_pop(boost::heap::detail::marked_heap_node*)(fibonacci_heap.hpp:745)
==14185==by 0x4015E7:boost::heap::fibonacci_heap::pop()(fibonacci_heap.hpp:398)
==14185==0x400E1C:main(test.cpp:34)
==14185== 
==14185== 
==14185==----附加到调试器?---[返回/N/N/Y/Y/C]--
看,您正在读取以前删除的内存。哎呀

任何事情都可能发生。发生什么取决于你的运气、你的电脑等


我使用了一个清理过的代码版本:,所以你可以交叉引用行号

对我来说听起来像UB。使用“弹出元素”的句柄不是类似于使用指向删除对象的指针吗?任何事情都可能发生?这是“我的代码有一个bug,为什么它不能达到我的预期效果”的另一个例子答案总是一样的:“这就是bug所做的,你不期望的事情。修复bug,神秘就会消失。”
sehe@desktop:/tmp$ valgrind --db-attach=yes ./test
==14185== Memcheck, a memory error detector
==14185== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==14185== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==14185== Command: ./test
==14185== 
first element in heap is :1 0.25
size of heap is :10
size of heap after pop is :9
first element in heap is now :8 1.23
element index 2 has time :3.6
==14185== Invalid read of size 8
==14185==    at 0x400F21: main (test.cpp:47)
==14185==  Address 0x5aa6d78 is 24 bytes inside a block of size 72 free'd
==14185==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14185==    by 0x402789: __gnu_cxx::new_allocator<boost::heap::detail::marked_heap_node<node> >::deallocate(boost::heap::detail::marked_heap_node<node>*, unsigned long) (new_allocator.h:110)
==14185==    by 0x401D2C: boost::heap::fibonacci_heap<node, boost::heap::compare<compare_node>, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_>::finish_erase_or_pop(boost::heap::detail::marked_heap_node<node>*) (fibonacci_heap.hpp:745)
==14185==    by 0x4015E7: boost::heap::fibonacci_heap<node, boost::heap::compare<compare_node>, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_>::pop() (fibonacci_heap.hpp:398)
==14185==    by 0x400E1C: main (test.cpp:34)
==14185== 
==14185== 
==14185== ---- Attach to debugger ? --- [Return/N/n/Y/y/C/c] ----