为什么两个程序中的一个会导致错误"*** glibc detected *** double free or corruption"而另一个则不会导致错误?

Why does one of the two programs cause "*** glibc detected *** double free or corruption" error while the other not?

本文关键字:错误 corruption or free 另一个 double detected 两个 一个 为什么 glibc      更新时间:2023-10-16

根据valgrind的说法,此问题是由以下代码引起的。我想删除列表中的元素,它包含与引用相同的整数值。

while(itr1!=list1.end())
{
 if(itr1->num==ref)
 {
  list1.erase(itr1);
 }
 else
 {itr1++;}
}

list1是一个STL列表,列表元素的类型是NODE,它是一个结构。num是NODE中的一个整数元素。itr1是list1的迭代器。ref是一个整数值。


但在我用下面的代码替换后,它是正确的

for(;itr1!=list1.end();itr1++)
{
 if(itr1->num==ref)
 {
  list1.erase(itr1);
  itr1--;
 }
}

我真的看不出这两个片段之间的区别。

我不知道你是否能解决代码不完整的问题。如果你需要,我可以发布所有的程序。谢谢

erase之后,被移除元素的迭代器无效。第二个代码之所以有效,是因为运气好,尽管这是未定义的行为,代码应该被认为是有缺陷的。

问题是在擦除元素后没有退出循环。指向已擦除元素的迭代程序无效。

while(itr1!=list1.end())
{
 if(itr1->num==ref)
 {
  list1.erase(itr1);
  break;
 }
 else
 {itr1++;}
}

您是否考虑过使用remove_if?

如果您知道列表中只有一个具有该值的元素(remove_if搜索所有事件),则效率可能会降低。

迭代程序实际上是伪装的指针。当您通过迭代器进行擦除时,该迭代器将变为无效;其类似于进行CCD_ 2或CCD_。解决方案与经典的C代码相同:

// Classic C code for removing all nodes matching 
// key_to_delete from doubly-linked list:
while (itr != list->null_node)
{
   node *next = itr->next; // Calculate next node now, while itr is valid!
   if (itr->data == key_to_delete) {
      itr->prev->next = itr->next;
      itr->next->prev = itr->prev;
      list_node_free(itr);
   }
   itr = next; // Advance to previously calculated next node
}

C++中与列表容器相同的概念:

while (itr1 != list1.end())
{
   std::list<whatever>::iterator next = itr1;  // calculate next iterator now
   next++;                                     // while itr1 is valid
   if (itr1->num == ref)
   {
     list1.erase(itr1);
   }
   itr1 = next;
}

列表迭代器上的erase操作只会使该迭代器(及其所有副本)无效。它不会使指向列表其他部分的迭代器无效。这就是为什么next的值在擦除后仍然存在并且可以使用的原因。