std::remove_if/find_if:双自由度或损坏

std::remove_if/find_if: Double free or corruption

本文关键字:if 自由度 损坏 remove std find      更新时间:2023-10-16

我定义了以下std::map:

 //The map holding the list of registered services per partition key.
 std::map<SRServicePartitionKey, std::vector<EndPointAddr*>* > mServiceMap;

我在下面指示了一个函数,其目的是删除vector中保存在上面定义的Map实例值中的特定EndPointAddr*指针。在实现以下场景后,我在gdb中获得SEGABORT:

  1. 添加多个项目到地图
  2. 使用下面的函数逐条删除。
  3. 重新添加已删除的项目(其中一部分)
  4. Delete one item ==>此时,我在GDB中得到一个带有以下消息的sigabort:

    * glibc检测到*/home/holb/design/eclb_cp/reps/v2/eclb_cp/build_output/ServiceRegistrar: double free or corruption (fasttop): 0x00007ffff0002e10 *

GDB Back trace在底部可用…

你认为下面这个移除函数有什么特别的地方是错误的?为什么我得到这个"双重免费或腐败"的错误?你认为我在删除函数中遗漏了什么,我首先找到要删除的项目,然后从向量中删除它,最后释放它。

<

删除功能/strong>

bool
ServiceRegistrar::removeService(const EndPointAddr & epAddrForRemoval)
{ 
  bool condErased = false;
  for(auto it = mServiceMap.begin(); it != mServiceMap.end(); ++it)
  {     
      std::cout << "tPartition [" 
                    << (*it).first.getInstanceNo() << ","
                    << (*it).first.getContext() << ","
                    << (*it).first.getVersion() << "]:"
                    << std::endl;
      std::vector<EndPointAddr*> * serviceList = (*it).second;  
      auto found = 
            std::find_if(serviceList->begin(),
                         serviceList->end(),
                         [epAddrForRemoval]( EndPointAddr* otherEPAddr ) 
                         { 
                          const EndPointTipcAddr & tipcAddrToRemove = epAddrForRemoval.getImmutableTipcAddress();
                          const EndPointTipcAddr & otherTipcAddr = otherEPAddr->getImmutableTipcAddress();                                                                                          
                          return (tipcAddrToRemove.compareTo(otherTipcAddr));                   
                         });      
     EndPointAddr * toBeDeAllocatedEP = *found;   
     auto toBeErasedEP = 
         std::remove_if(serviceList->begin(),
                        serviceList->end(),
                        [epAddrForRemoval]( EndPointAddr* otherEPAddr ) 
                        { 
                          const EndPointTipcAddr & tipcAddrToRemove = epAddrForRemoval.getImmutableTipcAddress();
                          const EndPointTipcAddr & otherTipcAddr = otherEPAddr->getImmutableTipcAddress();                                                                                          
                          return (tipcAddrToRemove.compareTo(otherTipcAddr));                   
                 });
    if(toBeErasedEP != serviceList->end())
    {         
      serviceList->erase(toBeErasedEP, serviceList->end());    
      condErased = true;
    }   
    if(toBeDeAllocatedEP != 0)
    {
      !!!!!!!!!!!!LINE 1396 is HERE!!!!!!!!!!!!!!!
      delete toBeDeAllocatedEP;
    }   
  } //end of For Loop
  return condErased;
}

GDB回溯

(gdb) bt
#0  0x00007ffff7026425 in raise () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007ffff7029b8b in abort () from /lib/x86_64-linux-gnu/libc.so.6
#2  0x00007ffff706439e in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#3  0x00007ffff706eb96 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#4  0x00007ffff7681540 in std::basic_string<char, std::char_traits<char>,     std::allocator<char> >::~basic_string() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x0000000000434604 in EndPointIpAddr::~EndPointIpAddr (this=0x7ffff0002fb0, __in_chrg=<optimized out>) at   /home/holb/DESIGN/ECLB_CP/REPs/V2/eclb_cp/src/control_components/../control_api/api_util/EndPointIpAddr.hpp:28
#6  0x0000000000434660 in EndPointAddr::~EndPointAddr (this=0x7ffff0002f90, __in_chrg=<optimized out>) at /home/holb/DESIGN/ECLB_CP/REPs/V2/eclb_cp/src/control_components/../control_api/api_util/EndPointAddr.hpp:36
#7  0x000000000043c97f in ServiceRegistrar::removeService (this=0x7fffffffdea0, epAddrForRemoval=...) at /home/holb/DESIGN/ECLB_CP/REPs/V2/eclb_cp/src/control_api/ServiceRegistrar.cpp:1396

您似乎没有检查它是否有效就使用了found。如果您没有找到一个值,而find_if返回serviceList->end(),那么您将取消对serviceList->end()的引用。

要存储这个解引用值的变量就是在稍后试图删除它时给您带来麻烦的变量。你确定你真的找到了一个匹配的值吗?