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

Я даже не знаю, с чего начать... 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) 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()
Аллегро-5.0.4-монолитно-мкр-debug.dll!636e0474()
Аллегро-5.0.4-монолитно-мкр-debug.dll!636d11fe()
Аллегро-5.0.4-монолитно-мкр-debug.dll! 636d0905 ()
allegro-5.0.4-monolith-md-debug.dll! 636d0703 () Project Nairim.exe! Приложение::~Application() Строка 104 + 0xf байт C++ Проект Nairim.exe! Приложение::`скалярное удаление деструктора '() + 0x2b байт C++ Проект Nairim.exe! Main() Строка 8 + 0x2b байт C++ Проект Nairim.exe!__tmainCRTStartup() Строка 555 + 0x19 байт C Проект Nairim.exe! MainCRTStartup () Строка 371 C kernel32.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 ответа

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

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

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

Другие вопросы по тегам