Точка останова пользователя из ниоткуда

У меня есть код в MS VC++ 6.0, который я отлаживаю. По какой-то причине в этот определенный момент, когда я пытаюсь удалить некоторую динамически выделенную память, она ломается, и я получаю всплывающее окно с сообщением «Точка останова пользователя вызвана из кода в бла-бла».., затем всплывает окно дизассемблирования, и я видеть

*memory address* int      3

Странно то, что НИГДЕ в коде, где я вызываю ассемблерную инструкцию, подобную этой (я думаю, что asm int 3 — это команда аппаратного прерывания для x86?)..

Что может быть причиной этого?

РЕДАКТИРОВАТЬ: ОТВЕТ: Мой код «уходил с конца» массива, но только в местах, отмеченных отладкой Visual Studio с 0xFDFDFDFD, который называется забором NoMan'sLand. Я думаю, что его также называют Off-by- одна ошибка. Этот массив не был связан с точкой, где я освобождал память, когда происходила ошибка. Что затрудняло обнаружение.. :(


person krebstar    schedule 22.12.2008    source источник
comment
Просто любопытно - вы нашли это, пошагово выполняя инструкции по сборке, чтобы узнать, что не понравилось отладочной куче, или вам помог какой-то другой инструмент/метод?   -  person Michael Burr    schedule 22.12.2008
comment
Я просмотрел этот сайт highprogrammer.com/alan/windev/visualstudio.html в котором говорилось: это 0xFDFDFDFD было значением памяти, которое отладчик MSVC++ использовал для указания границы в массиве для обнаружения ошибок «один за другим». Я проверил свои указатели и прошел итерации в одиночку.   -  person krebstar    schedule 23.12.2008
comment
исходный код и обнаружил, что я не ограничил один из своих массивов должным образом. Так что я думаю, что это был просто случай, когда мне нужно было правильно проверить мои указатели :)   -  person krebstar    schedule 23.12.2008
comment
Просто к сведению - вот сообщение, в котором подробно описывается большинство специальных значений заполнения, которые использует куча отладки: stackoverflow.com/questions/370195/   -  person Michael Burr    schedule 23.12.2008
comment
Да, я считаю, что ссылка, которую я дал выше, содержала ту же информацию в разделе «Забавные значения памяти».. :) Может кто-нибудь закрыть это? Мне не хватает репутации :P   -  person krebstar    schedule 23.12.2008


Ответы (2)


Вы, вероятно, сталкиваетесь с кодом в подпрограммах отладки кучи, которые обнаружили повреждение кучи.

Как выглядит стек вызовов, когда вы нажмете Int 3?

Редактировать: основываясь на трассировке стека в ваших комментариях, подпрограмма _CrtIsValidHeapPointer() говорит, что освобождаемый указатель неисправен. Вот фрагмент кода из исходного кода MSVC DBGHEAP.C:

    /*
     * If this ASSERT fails, a bad pointer has been passed in. It may be
     * totally bogus, or it may have been allocated from another heap.
     * The pointer MUST come from the 'local' heap.
     */
    _ASSERTE(_CrtIsValidHeapPointer(pUserData));

pUserData будет значением указателя, который вы удаляете.

person Michael Burr    schedule 22.12.2008
comment
НТДЛЛ! 7c90120e() NTDLL! 7c95d454() NTDLL! 7c96c5cf() NTDLL! 7c9603b0() ЯДРО32! 7c85f8d7() - person krebstar; 22.12.2008
comment
_CrtIsValidHeapPointer(const void * 0x04880068) строка 1697 _free_dbg_lk(void * 0x04880068, int 1) строка 1044 + 9 байт - person krebstar; 22.12.2008
comment
Я думаю, вам нужно загрузить символы DLL системы Windows. Я не думаю, что MSVC 6 поддерживает это (но я могу ошибаться) — вы можете загрузить средства отладки для Windows и использовать отладчик WinDBG: microsoft.com/whdc/devtools/debugging/installx86.mspx - person Michael Burr; 22.12.2008
comment
Так как он ломается в _CrtIsValidHeapPointer(), вы, вероятно, освобождаете указатель с фиктивным значением. - person Michael Burr; 22.12.2008
comment
Спасибо за ссылку. Что означает фиктивное значение? Мусор, например, указатель не был изначально инициализирован? Я почти уверен, что это было :( - person krebstar; 22.12.2008
comment
Кстати, прежде чем он сломается, я получаю сообщение в окне вывода, в котором говорится Исключение первого шанса в XXXXX.exe (NTDLL.DLL): 0xC0000005: нарушение прав доступа. Однако это не сломается, и несколько строк ниже по коду, где он сломается. - person krebstar; 22.12.2008
comment
Я бы сказал, поставьте точку останова на ваш вызов удаления, а затем начните трассировку в сборке — вы можете следить за исходным кодом среды выполнения в каталоге VC98\CRT\SRC. - person Michael Burr; 22.12.2008
comment
Я не слишком уверен насчет трассировки в ассемблере, я еще не очень хорошо с этим разбираюсь.. Но спасибо :) Думаю, я попытаюсь проверить, действителен ли указатель.. :) - person krebstar; 22.12.2008
comment
Просто убедитесь, что значение, которое вы удаляете, совпадает с значением, которое вы получаете из нового. Если это так, убедитесь, что вы не удаляете его более одного раза. - person Michael Burr; 22.12.2008
comment
Я только что проверил это, и указатель действителен. есть адрес памяти, и я могу изложить его, чтобы показать его члены. Указанный указатель является указателем на класс. В моем исполнении создан только один, и это единственная точка, где он удаляется :( - person krebstar; 22.12.2008
comment
Может быть, покажите код, который создает указатель - вы используете оператор new для установки указателя? - person Michael Burr; 22.12.2008
comment
Является ли память, на которую указывает указатель, выделенной в одном модуле (EXE или DLL) и освобожденной в другом? - person Michael Burr; 22.12.2008
comment
Нет, память выделяется и освобождается в одном и том же модуле (DLL).. :( и да, я использую new.. получается так.. pointer = new CustomClass(initializer); и освобождается указателем удаления; - person krebstar; 22.12.2008
comment
Хм - я думаю, вам придется перейти к инструкциям по сборке x86, чтобы увидеть, что не нравится среде выполнения (или вы можете скомпилировать среду выполнения, чтобы получить доступ к исходному коду - но я думаю, что это может быть более болезненным, чем пробираться через сборку). - person Michael Burr; 22.12.2008

(Я думаю, что asm int 3 — это команда аппаратного прерывания для x86?

Да. Это называется "аппаратная точка останова". Если вы используете отладчик VS с исходным кодом проекта, это похоже на точку останова (но в коде). Начиная с vs2005, если ваше приложение запускается без какого-либо отладчика, приложение просто падает, как если бы оно запускало неуправляемое исключение.

Во многих компаниях есть простой макрос, используемый для добавления этой точки останова в код. Это может заменить утверждения и исключения в некоторых (сложных и редких) случаях:

#define BREAKPOINT __asm { int 3; }

BREAKPOINT;

Видеть :

Поэтому я предлагаю поискать какой-нибудь макрос или объект, делающий это, или, может быть, он появляется в модуле (dll/lib), кода которого у вас нет?

person Klaim    schedule 22.12.2008
comment
Да, в программе открывается какая-то dll/lib, и у меня нет для нее исходного кода. Однако я не думаю, что это причина. Майкл Бёрр кажется более вероятным.. В любом случае спасибо :) - person krebstar; 22.12.2008