5

W mojej aplikacji dostaję ten błąd:Heap korupcja - "Heap wolnego bloku 61af0f0 modyfikowane w 61af194 po tym jak został uwolniony" C++

HEAP[App.exe]: HEAP: Free Heap block 61af0f0 modified at 61af194 after it was freed 

Oto stos wywołań:

[email protected]() Unknown 
    [email protected]@24() Unknown 
    [email protected]() Unknown 
    [email protected]() Unknown 
    [email protected]@24() Unknown 
    [email protected]() Unknown 
> msvcr110d.dll!_heap_alloc_base(unsigned int size) Line 57 C 
    msvcr110d.dll!_heap_alloc_dbg_impl(unsigned int nSize, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp) Line 431 C++ 
    msvcr110d.dll!_nh_malloc_dbg_impl(unsigned int nSize, int nhFlag, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp) Line 239 C++ 
    msvcr110d.dll!_nh_malloc_dbg(unsigned int nSize, int nhFlag, int nBlockUse, const char * szFileName, int nLine) Line 302 C++ 
    msvcr110d.dll!malloc(unsigned int nSize) Line 56 C++ 
    msvcr110d.dll!operator new(unsigned int size) Line 59 C++ 
    App.exe!std::_Allocate<char>(unsigned int _Count, char * __formal) Line 28 C++ 
    App.exe!std::allocator<char>::allocate(unsigned int _Count) Line 591 C++ 
    App.exe!std::basic_stringbuf<char,std::char_traits<char>,std::allocator<char> >::overflow(int _Meta) Line 152 C++ 
    msvcp110d.dll!std::basic_streambuf<char,std::char_traits<char> >::sputc(char _Ch) Line 196 C++ 
    msvcp110d.dll!std::ostreambuf_iterator<char,std::char_traits<char> >::operator=(char _Right) Line 634 C++ 
    msvcp110d.dll!std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::_Put(std::ostreambuf_iterator<char,std::char_traits<char> > _Dest, const char * _Ptr, unsigned int _Count) Line 1553 C++ 
    msvcp110d.dll!std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::_Iput(std::ostreambuf_iterator<char,std::char_traits<char> > _Dest, std::ios_base & _Iosbase, char _Fill, char * _Buf, unsigned int _Count) Line 1544 C++ 
    msvcp110d.dll!std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char,std::char_traits<char> > _Dest, std::ios_base & _Iosbase, char _Fill, long _Val) Line 1216 C++ 
    msvcp110d.dll!std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char> > >::put(std::ostreambuf_iterator<char,std::char_traits<char> > _Dest, std::ios_base & _Iosbase, char _Fill, long _Val) Line 1137 C++ 
    msvcp110d.dll!std::basic_ostream<char,std::char_traits<char> >::operator<<(int _Val) Line 311 C++ 
    App.exe!TUtil::intToString(int val) Line 43 C++ 
    App.exe!TFontManager::getFont(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & filename, int size) Line 15 C++ 
    App.exe!TButton::draw() Line 55 C++ 
    App.exe!TWindow::draw() Line 203 C++ 
    App.exe!TGUIManager::drawObjects() Line 49 C++ 
    App.exe!TGameAppLayer::gameCycle() Line 456 C++ 
    App.exe!TGameAppLayer::mainLoop() Line 520 C++ 
    App.exe!wWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) Line 36 C++ 
    App.exe!__tmainCRTStartup() Line 528 C 
    App.exe!wWinMainCRTStartup() Line 377 C 
    [email protected]@12() Unknown 
    [email protected]() Unknown 
    [email protected]() Unknown 

Z tego co wiem, błąd, który otrzymuję, jest spowodowany przez dostęp (ponownie) do bloku pamięci, który został już uwolniony. To już trzeci dzień próbowania sprawdzenia, co jest nie tak z moim kodem. W tym czasie znalazłem kilka małych wycieków pamięci, które już naprawiłem, a teraz Visual Leak Detector mówi mi, że nie wykrywa żadnego wycieku.

Jednak problem z korupcją sterty pozostaje.

W każdym miejscu mojego kodu w miejscu, w którym używany jest operator "usuń", najpierw sprawdzam, czy wskaźnik nie jest nullptr. Jeśli nie, ustaw ją na nullptr:

if(m_pVar != nullptr) 
{ 
    delete m_pVar; 
    m_pVar = nullptr; 
} 

Więc wydaje się, że nie powinno być problemu z uwalniając sam blok pamięci więcej niż jeden raz.

Próbowałem dowiedzieć się czegoś z tego stosu wywołań, ale to jest miejsce, w którym chciałbym poprosić o pomoc. W stosie wywołań wydaje się, że problem jest z przydziałem string, ale co dokładnie może to oznaczać? Ostatnim MY funkcja, która jest wywoływana jest string TUtil::intToString(int val) Line 43, więc to może być łatwiejsze, jeśli pokażę wam ciało tej funkcji:

std::string TUtil::intToString(int val) 
{ 
    std::ostringstream s; 
    s << val;     // Here's line 43 
    return s.str(); 
} 

Czasami nazywamy stos jest inny, więc string TUtil::intToString(int val) funkcja nawet nie istnieje w nim, ale ZAWSZE ma coś wspólnego z alokacjami string.

Mam nadzieję, że jest jasne, co właśnie powiedziałem. Jeśli potrzebujesz więcej informacji, proszę powiedz mi, a ja przekażę to w edycji na to pytanie.

+3

Jesteś na platformie, na której Valgrind jest opcją? –

+0

Jeśli pracujesz na systemie Linux, spróbuj sprawdzić swoją aplikację za pomocą Valgrind – Vargan

+2

Czy zdefiniowałeś konstruktora kopiowania i operatora przypisania lub jawnie zabroniłeś kopiowania instancji klasy, która ma członka 'm_pVar'? – hmjd

Odpowiedz

9

So from what I know, the error I'm getting is caused by accessing (deleting again) block of memory which was already freed.

Chyba że jest coś, o czym wiesz i nie mówisz, powyższe może być czerwonym śledziem. Błąd może być również oznacza, że ​​modyfikujesz pamięć przez zwisający wskaźnik lub z powodu przekroczenia bufora.

Jeśli kiedykolwiek tworzysz kopie wskaźników (jawnie lub nie definiując operatorów konstruktorów kopiowania/przypisywania), ustawienie m_pVar = nullptr po usunięciu spowoduje brak gwarancji dla podwójnych kasowań, nie mówiąc już o innych typach błędów pamięci.

Jeśli nie możesz znaleźć problemu, badając kod, najlepszym rozwiązaniem może być narzędzie takie jak Valgrind lub Purify.

+4

Dziękujemy za odpowiedź NPE! Przepraszam za nieco spóźnioną odpowiedź, ale wciąż próbowałem znaleźć problem zgodnie z podpowiedziami, które mi daliście, a wreszcie znalazłem to dzięki programom "Application Verifier" i "Debug Diagnostics Tool". Wygląda na to, że używam wskaźnika do bloku pamięci, który został już uwolniony. –

2

Awaria podczas malloc jest pewnym znakiem uszkodzenia pamięci i może, ale nie musi, być skutkiem podwójnego usunięcia. Korupcja zdarzyła się w innej części twojego kodu i niestety efekt wtargnął do twojego wadliwego kodu, który jest zdecydowanie niewinny. Jeśli to możliwe, spróbuj przenieść aplikację do systemu, w którym możesz uruchomić valgrind

+0

Dziękuję Abhijit za odpowiedź. Problem polegał na użyciu wskaźnika do bloku pamięci, który został już zwolniony. –

Powiązane problemy