2011-04-24 17 views
0

我已經閱讀了大量關於內存損壞的文章,看起來它可能是一個相當難以解決的問題。當我在我的linux機器上運行我的代碼時,它運行良好,valgrind不報告任何泄漏或錯誤。但是,當我使用VS2008在我的實驗室的Windows機器上運行代碼時,出現錯誤的alloc錯誤,使用_RAISE(nomem)停止。這對我來說似乎很奇怪,因爲我會期望valgrind能夠抓住它。掙扎 - 又一個內存損壞問題,壞分配(C++,VS 2008)

void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc) 
    {  // try to allocate size bytes 
    void *p; 
    while ((p = malloc(size)) == 0) 
      if (_callnewh(size) == 0) 
      {  // report no memory 
      static const std::bad_alloc nomem; 
      _RAISE(nomem); 
      } 

    return (p); 
    } 

從我讀過,好像這個問題往往來自於過去寫的內存分配塊的結束或已釋放後,但我沒有任何運氣查明,可能是發生。這是我嘗試運行Release版本後的調用堆棧。

[email protected]() + 0x58 bytes 
msvcr90.dll!_CxxThrowException(void * pExceptionObject=0x0040f6d4, const _s__ThrowInfo * pThrowInfo=0x6f63d604) Line 161 C++ 
msvcr90.dll!operator new(unsigned int size=4) Line 63 + 0x17 bytes C++ 
tempMem.exe!std::vector<unsigned char,std::allocator<unsigned char> >::vector<unsigned char,std::allocator<unsigned char> >(const std::vector<unsigned char,std::allocator<unsigned char> > & _Right=[...]()) Line 500 + 0x31 bytes C++ 
tempMem.exe!DendriteSegment::DendriteSegment(const DendriteSegment & __that={...}) + 0x4a bytes C++ 
tempMem.exe!std::list<DendriteSegment,std::allocator<DendriteSegment> >::_Buynode(std::_List_nod<DendriteSegment,std::allocator<DendriteSegment> >::_Node * _Next=0x005d84d0, std::_List_nod<DendriteSegment,std::allocator<DendriteSegment> >::_Node * _Prev=0x0093af50, const DendriteSegment & _Val={...}) Line 1208 C++ 
tempMem.exe!TP::adaptSegments(Cell * & cellToAdapt=0x005d8450, std::list<segUpdate,std::allocator<segUpdate> > & segUpdateList=[1]({segToUpdate=0x00000000 synapseChanges=[0]() newSynapsesToAdd=[2](0x005bc8f8 {DSlist=[19]({sequenceSegment=true synapse=[3](0x005d79a0 {DSlist={...} connected=0x005d7af8 currentState=0x005d79c0 ...},0x005d7ef8 {DSlist={...} connected=0x005d8050 currentState=0x005d7f18 ...},0x005d8450 {DSlist={...} connected=0x005d85a8 currentState=0x005d8470 ...}) permanence=[3](80 'P',80 'P',80 'P') ...},. ), bool posReinforce=true) Line 701 + 0x1b bytes C++ 
tempMem.exe!Level::TPlearning() Line 236 + 0x26 bytes C++ 
tempMem.exe!main(int argc=, char * * argv=) Line 96 C++ 
msvcr90.dll!_encode_pointer(void * ptr=0x6f5d3607) Line 114 + 0x5 bytes C 
0069ee20() 
msvcr90.dll!_initterm(void (void)* * pfbegin=0x00000001, void (void)* * pfend=0x000a1ef8) Line 903 C 
tempMem.exe!__tmainCRTStartup() Line 582 + 0x17 bytes C 
[email protected]@12() + 0x12 bytes  
[email protected]() + 0x27 bytes 
[email protected]() + 0x1b bytes 

當從這裏

#ifdef _WIN64 
return HeapAlloc(_crtheap, 0, size ? size : 1); 
#else /* _WIN64 */ 
if (__active_heap == __SYSTEM_HEAP) { 
    return HeapAlloc(_crtheap, 0, size ? size : 1); 
} else 
if (__active_heap == __V6_HEAP) { 
    if (pvReturn = V6_HeapAlloc(size)) { 
     return pvReturn; 
    } 
} 

在運行調試會話我得到一個不同的錯誤(這似乎並不雖然發生的時間......)

return HeapAlloc(_crtheap, 0, size ? size : 1); 

這種情況的調用堆棧是

[email protected]() + 0x23 bytes  
[email protected]@24() + 0x57dbc bytes 
[email protected]() + 0x502a bytes 
[email protected]() + 0xb5 bytes 
[email protected]@24() + 0x57c17 bytes 
[email protected]() + 0x502a bytes 
msvcr90d.dll!_heap_alloc_base(unsigned int size=38) Line 105 + 0x28 bytes C 
msvcr90d.dll!_heap_alloc_dbg_impl(unsigned int nSize=2, int nBlockUse=1, const char * szFileName=0x00000000, int nLine=0, int * errno_tmp=0x0052f284) Line 427 + 0x9 bytes C++ 
msvcr90d.dll!_nh_malloc_dbg_impl(unsigned int nSize=2, int nhFlag=0, int nBlockUse=1, const char * szFileName=0x00000000, int nLine=0, int * errno_tmp=0x0052f284) Line 239 + 0x19 bytes C++ 
msvcr90d.dll!_nh_malloc_dbg(unsigned int nSize=2, int nhFlag=0, int nBlockUse=1, const char * szFileName=0x00000000, int nLine=0) Line 296 + 0x1d bytes C++ 
msvcr90d.dll!malloc(unsigned int nSize=2) Line 56 + 0x15 bytes C++ 
msvcr90d.dll!operator new(unsigned int size=2) Line 59 + 0x9 bytes C++ 
tempMem.exe!std::_Allocate(unsigned int _Count=2) Line 43 + 0xc bytes C++ 
tempMem.exe!std::allocator<uint8_t>::allocate(unsigned int _Count=2) Line 145 + 0x13 bytes C++ 
tempMem.exe!std::::_Buy(unsigned int _Capacity=2) Line 1115 + 0x14 bytes C++ 
tempMem.exe!std::::vector(const std::vector<uint8_t, std::allocator<uint8_t> > & _Right=[2](80 'P',80 'P')) Line 501 + 0x2b bytes C++ 
tempMem.exe!DendriteSegment::DendriteSegment() + 0x8b bytes C++ 
tempMem.exe!std::_Construct(DendriteSegment * _Ptr=0x007e7490, const DendriteSegment & _Val={...}) Line 52 + 0x97 bytes C++ 
tempMem.exe!std::allocator<DendriteSegment>::construct(DendriteSegment * _Ptr=0x007e7490, const DendriteSegment & _Val={...}) Line 155 + 0x15 bytes C++ 
tempMem.exe!std::::_Buynode(std::_List_nod<DendriteSegment, std::allocator<DendriteSegment> >::_Node * _Next=0x00637f60, std::_List_nod<DendriteSegment, std::allocator<DendriteSegment> >::_Node * _Prev=0x00bfcb50, const DendriteSegment & _Val={...}) Line 1199 + 0x47 bytes C++ 
tempMem.exe!std::::_Insert(std::list<DendriteSegment, std::allocator<DendriteSegment> >::_Const_iterator<1> _Where={sequenceSegment=true synapse=[0]() permanence=[0]() ...}, const DendriteSegment & _Val={...}) Line 718 + 0x65 bytes C++ 
tempMem.exe!std::::push_back(const DendriteSegment & _Val={...}) Line 670 + 0x6f bytes C++ 
tempMem.exe!TP::adaptSegments(Cell * & cellToAdapt=0x00637ee8, std::list<segUpdate, std::allocator<segUpdate> > & segUpdateList=[1](...), bool posReinforce=true) Line 701 + 0x16 bytes C++ 
tempMem.exe!TP::phase3() Line 949 + 0x3e bytes C++ 
tempMem.exe!Col::TPphase3() Line 398 + 0xd bytes C++ 
tempMem.exe!Level::TPlearning() Line 236 + 0x4a bytes C++ 
tempMem.exe!Network::runTPlearning() Line 93 + 0xd bytes C++ 
tempMem.exe!main(int argc=1, char * * argv=0x006f62a0) Line 93 + 0xd bytes C++ 
tempMem.exe!__tmainCRTStartup() Line 582 + 0x19 bytes C 
tempMem.exe!mainCRTStartup() Line 399 C 
[email protected]@12() + 0x12 bytes  
[email protected]() + 0x27 bytes 
[email protected]() + 0x1b bytes  

這是我第一次調試這種類型的問題,我希望我只是忽略/誤解明顯的東西...

下面是調用堆棧(版本)

對應此行的adaptSegments函數的代碼
tempMem.exe!TP::adaptSegments(Cell * & cellToAdapt=0x005d8450, std::list<segUpdate,std::allocator<segUpdate> > & segUpdateList=[1]({segToUpdate=0x00000000 synapseChanges=[0]() newSynapsesToAdd=[2](0x005bc8f8 {DSlist=[19]({sequenceSegment=true synapse=[3](0x005d79a0 {DSlist={...} connected=0x005d7af8 currentState=0x005d79c0 ...},0x005d7ef8 {DSlist={...} connected=0x005d8050 currentState=0x005d7f18 ...},0x005d8450 {DSlist={...} connected=0x005d85a8 currentState=0x005d8470 ...}) permanence=[3](80 'P',80 'P',80 'P') ...},. ), bool posReinforce=true) Line 701 + 0x1b bytes 

bool TP::adaptSegments(Cell *& cellToAdapt, 
std::list<segUpdate> & segUpdateList, bool posReinforce) 
{ 
std::list<segUpdate>::iterator curSegUpdate; 
std::list<activeSynapsePair>::iterator curSyn; 
std::list<Cell *>::iterator synToAdd; 
int size = 0; 

//for each segUpdate element in the cell's segUpdateList 
for (curSegUpdate = segUpdateList.begin(); 
     curSegUpdate != segUpdateList.end(); ++curSegUpdate) 
{ 
    //if the segment already exists 
    if (curSegUpdate->segToUpdate != NULL) 
    { 
     //if sequence segment flag is true, set it on DS 
     if(curSegUpdate->sequenceSegment == true) 
     {curSegUpdate->segToUpdate->sequenceSegment = true;} 
     if (posReinforce == true) 
     { 
      //for each synapses permanence pair in segUpdate 
      for (curSyn = (curSegUpdate-> 
      synapseChanges.begin()); 
      curSyn !=(curSegUpdate->synapseChanges.end()); 
      ++curSyn) 
      { 
       //decrement inactive synapses 
       if (curSyn->second == false) 
       { 
        if (*(curSyn->first)- 
         permanenceDec < 0) 
         {*(curSyn->first) = 0;} 
        else 
        {*(curSyn->first)-= 
          permanenceDec;} 
       } 
       //increment active synapses 
       else if (curSyn->second == true) 
       { 
        if (*(curSyn->first)+ 
         permanenceInc > 100) 
         {*(curSyn->first) =100;} 
        else 
        {*(curSyn->first)+= 
          permanenceInc;} 
       } 
      } 
     } 
     else if (posReinforce == false) 
     { 
      //for each synapses permanence pair in segUpdate 
      for (curSyn = (curSegUpdate-> 
       synapseChanges.begin()); 
      curSyn !=(curSegUpdate->synapseChanges.end()); 
      ++curSyn) 
      { 
       //decrement active synapses 
       if (curSyn->second == true) 
       { 
        if (*(curSyn->first)- 
         permanenceDec < 0) 
         {*(curSyn->first) = 0;} 
        else 
        {*(curSyn->first)-= 
          permanenceDec;} 
       } 
      } 
     } 
     //if adding synapses to an existing segment 
     if (curSegUpdate->newSynapsesToAdd.empty()==false) 
     { 
      if (curSegUpdate->segToUpdate->synapse.size() 
           <MAX_NUM_SYN) 
      { 
      //for each synapses in newSynapses 
      for (synToAdd = 
       curSegUpdate->newSynapsesToAdd.begin(); 
       synToAdd != curSegUpdate-> 
       newSynapsesToAdd.end(); ++synToAdd) 
      { 
       //add new synapse to list 
       curSegUpdate->segToUpdate-> 
        synapse.push_back(*synToAdd); 
       //and permenance with initialPerm 
       curSegUpdate->segToUpdate-> 
       permanence.push_back(initialPerm); 
      } 
      }//if less than MAX_NUM_SYN 
     } 
    }//end if segment already exists 

//if segment doesn't exist, create a new segment & add synapses 
    else if (curSegUpdate->segToUpdate == NULL) 
    { 
     size = curSegUpdate->newSynapsesToAdd.size(); 
     if (size != 0) 
     { 
     DendriteSegment myNewSeg; //create a new DS 
     //set sequenceSegment flag if it is true 
     if (curSegUpdate->sequenceSegment == true) 
     {myNewSeg.sequenceSegment = true;} 

     std::copy(curSegUpdate->newSynapsesToAdd.begin(), 
      curSegUpdate->newSynapsesToAdd.end(), 
      std::back_inserter(myNewSeg.synapse)); 

     myNewSeg.permanence.resize(size, initialPerm);  

     //then add it to the cells list of DS 
     cellToAdapt->DSlist.push_back(myNewSeg); 
     }//if size not 0 
    } 
} 
return true;} 

我的下一步是嘗試應用程序驗證程序。我嘗試了英特爾Inspector XE 2011,但它似乎沒有檢測到任何相關的內存問題。

更新:使用gflags我發現我的悲哀的原因是由於指向std :: vector中的元素。使用myVector.push_back(newElem)向矢量添加元素,導致指向矢量元素的指針變爲壞。我將std :: list替換爲不具有相同問題的向量(請參閱here

回答

1

嘗試使用Windows的Microsoft調試工具中的gflags(http://www.google.ca/search?sourceid=chrome & ie = UTF-8 & q =調試+工具+ for + windows)工具包。它允許您使用調試堆運行,以便在發生問題時捕獲問題,而不是在發生崩潰的站點之後很長時間發生的隨機問題。