Куча коррупции - PullRequest
       27

Куча коррупции

2 голосов
/ 10 сентября 2011

Я даже не знаю, с чего начать ... Visual Studio продолжает выдавать мне ошибку повреждения кучи, когда я закрываю свою программу.Положение, в котором это ломается, изменяется.В течение 40 с лишним часов я потратил на изменение кода (удаление интеллектуальных указателей, удаление скрытых реализаций, повторное добавление интеллектуальных указателей, запрет на копирование каждого класса, закрытие деструкторов и т. Д.), 95% времени, когда я просматривал вызовстек это было связано с boost :: shared_ptr и std :: shared_ptr (я переключился между ними, чтобы посмотреть, поможет ли это), примерно в 75% случаев это было связано с удалением класса CLevel с помощью shared_ptr.

После того, как я сделал деструкторы приватными и создал функцию для их удаления, я подумал, что сузил его до вызова вызова delete для указателя на CLevel.Примерно в 50% случаев это было сразу после звонка, и это дало мне ошибку.Я вошел в CLevel и наблюдал за каждой переменной, чтобы убедиться, что они удалялись нормально, и они были, код перешел в базовый класс и вышел, именно на этом выходе выскочила ошибка кучи.Но я не мог понять, что было не так, плюс, это не всегда давало и ошибки там.Иногда выкидывал ошибку после и я тоже верю раньше.Из-за этого НАСТОЯТЕЛЬНО трудно найти проблему, тем более что это происходило в других классах (я думаю, что только в CEntity или CEntityManager).

Я думал, что это должен был быть Boost, делающий что-то странное, потому что после удаления умных указателей извнутри реализаций классов, и вместо этого, когда я запросил новый экземпляр класса (в частности, CLevel и CEntity), программа выдала ошибку после выхода из Application.run () (интеллектуальные указатели выполняются внутри).стек вызовов показал, что ошибка произошла сразу после или через некоторое время после «скалярного удаления деструктора».

Во многих случаях перерыв был внутри free.c.На данный момент это на realloc.c.строка 85. Эта ошибка похожа на месячную задержку, я так устала от попыток исправить ее, что я решила не удалять какие-либо классы при выходе из программы, но я действительно не хочу так поступать, что если я захочучто будет сделано после выхода?Несколько минут назад ошибка произошла дважды при выходе.Один из них, похоже, был связан с умным указателем на ALLEGRO_EVENT_QUEUE и ALLEGRO_TIMER, я сделал их обычными указателями и вручную удалил их, а второй ушел.

Сейчас это стек вызовов:

ntdll.dll! 771b0474 () [Указанные ниже кадры могут быть неправильными и / или отсутствовать, символы не загружены для ntdll.dll] ntdll.dll! 7716afc3 ()
ntdll.dll! 7716b0ad ()ntdll.dll! 77195665 ()
ntdll.dll! 77172990 () ntdll.dll! 77195665 ()
ntdll.dll! 77172990 () ntdll.dll! 77121fec ()

msvcr100d.dll! _realloc_base (void * pBlock, unsigned int newsize) Строка 85 + 0x17 байт C msvcr100d.dll! realloc_help (void * pUserData, unsigned int * pnNewSize, int nBlockUse, const char * szFileName, int nloc line, int nLine)832 + 0x10 байт C ++ msvcr100d.dll! _Realloc_dbg (void * pUserData, unsigned int nNewSize, int nBlockUse, const char * szFileName, int nLine) Строка 1040 + 0x1b байт C ++ msvcr100d.dll! Realloc (недопустимый) unsigned)Линия 60+ 0x13 байт C ++ allegro-5.0.4-monolith-md-debug.dll! 636d78c0 ()
allegro-5.0.4-monolith-md-debug.dll! 636e0474 ()
allegro-5.0.4-monolith-md-debug.dll! 636d11fe ()
allegro-5.0.4-monolith-md-debug.dll! 636d0905 ()
allegro-5.0.4-monolith-md-debug.dll! 636d0703 () Проект Nairim.exe! Приложение :: ~ Приложение () Строка 104 + 0xf байт C ++ Проект Nairim.exe! Приложение :: `скалярное удаление деструктора '() + 0x2b байт C ++ Проект Nairim.exe! Main () Строка 8 + 0x2bC ++ Проект Nairim.exe! __tmainCRTStartup () Строка 555 + 0x19 байт C Проект Nairim.exe! mainCRTStartup () Строка 371 Ckernel32.dll! 750f339a () ntdll.dll! 77119ed2 ()
ntdll.dll! 77119ea5 ()

Это код, который, по моему мнению, был проблемой, когда дело дошло до функции удаления (Примечание: эта функция никогда не существовала, когда она впервые появилась месяц назад.)

void PN::CLevelManager::destroyLevel(const pLevel _ptr)
{
    assert(LevelMgr.get() != NULL);
    std::cout << std::endl << LevelMgr.get();
    auto iter = std::find(LevelMgr->m_levelList.begin(), LevelMgr->m_levelList.end(), _ptr);
    if (iter != LevelMgr->m_levelList.end())
        LevelMgr->m_levelList.erase(iter);
    delete _ptr;
}

Есть и другие подобные.

Это мой полный код (это много): https://github.com/NaturalDre/Nairim

Я программист-самоучка, поэтому, если код выглядит ужасно или плохо структурирован, я прошу прощения.

Было бы здорово, если бы кто-то указал мне на этот вопрос. Такие вещи меня обескураживают. Мне нравятся компьютеры, потому что все фиксировано, а не переменно (если вы это сделаете, это произойдет, даже если это не то, что вы ожидаете). Эта ошибка прыгает вокруг, и подобные вещи сводят меня с ума. И никакие соответствующие данные в программе не изменяются. CLevel просто читает файл, создает карту, а затем рисует ее, когда это необходимо.

Кроме того, помните, что я быстро менял многие вещи, поэтому некоторые вещи могут показаться странными или не реализованными полностью.

Ответы [ 3 ]

2 голосов
/ 11 сентября 2011

Время заняться WinDbg , GFlags и AppVerifier .Это инструменты, которые могут привести к аварийному завершению программы ранее и позволяют перейти в отладчик, чтобы увидеть, где произошло повреждение памяти.

0 голосов
/ 25 января 2013

AppVerifier не поддерживается после VS 2008. Вы можете получить некоторые альтернативы, такие как C ++ Memory Validator. Это очень полезный и мощный инструмент.

0 голосов
/ 28 ноября 2012

Я могу подтвердить, что AppVerifier - отличный способ.Я сам использовал это для некоторых неприятных ошибок, и это работает хорошо.Не пробовал WinDbg и GFlags, но App Verifier и Visual studio окончательно поработали, чтобы показать, где возникают проблемы.

...