Отладка приложений


Окна Memory и Disassembly - часть 4


Однако мы убедили его, что найденное ничего не доказывает и что необходимо продолжить проверку использования памяти. Оказалось, что элемент управления "не виноват", и новой гипотезой стало предположение, что реальную проблему содержало само приложение. Авария же в стороннем элементе управления была просто совпадением.

Проверка исходного кода показала, что приложение было полным 32-разрядным Windows-приложением и ничего не делало с дескрипторной памятью. Тогда мы проверили функцию печати — ее код выглядел безупречно.

Было решено сузить область дублирования аварии. После нескольких прогонов оказалось, что для аварийного останова нужно было лишь открыть диалоговое окно Print и изменить ориентацию печатной страницы, а после закрытия окна Print надо было просто повторно открыть его. Аварийный останов происходил вскоре после второго закрытия окна. Ориентация страницы, вероятно, просто изменяла байт где-то в памяти, что и служило причиной аварии.

Хотя при начальном чтении код выглядел безупречно, я просматривал каждую строку в обратном порядке и перепроверял ее по документации MSDN. Через 10 минут ошибка была найдена. Команда сохраняла структуру данных PRINTDLG, используемую для инициализации диалогового окна Print, с помощью API-функции PrintDlg. Третье поле в этой структуре — hDevMode — является значением дескрипторной памяти, которую выделяет диалоговое окно Print. Ошибка состояла в том, что разработчики использовали это значение памяти как регулярный указатель и должным образом не разыменовывали дескриптор или вызывали функцию GlobalLock для дескриптора. Изменяя значения в структуре DEVMODE, на самом деле они выполняли запись в глобальную таблицу дескрипторов процесса. Эта таблица является участком памяти, в котором хранятся все распределения динамической памяти дескрипторов. При случайной записи в глобальную таблицу дескрипторов обращение к GlobalAlloc использует неправильные смещения, а значения, вычисленные по такой таблице, приводили к тому, что функция GlobalAlloc возвращала некорректные указатели.




Начало  Назад  Вперед