Помимо Aero Glass, одна из наиболее заметных
фишек Windows Vista —
Sidebar с набором гаджетов, таких как часы, RSS
читалка, просмотрщик фотографий и т.п. Штука сама по себе удобная, а простота
разработки гаджетов привела к появлению тысяч сторонних программ, найти их можно
например на

Windows Vista Gadget Gallery
. Я ради любопытства скачивал и устанавливал
некоторые из них, в определенных ситуациях и оставлял в стандартной настройке
сайдбара не испытывая никаких проблем. Спустя
несколько дней после установки очередного пакета гаджетов я заметил, что одна из
программ с часами прекратила свое обновление и я преступил к расследованию.

Моя система в остальном функционировала нормально, так
что моим первым действием было посмотреть все ли в порядке с конфигурацией
Sidebar-а. Я кликнул правой кнопкой мыши на
поле Sidebar-а и выбрал пункт Properties, но вместо
показа свойств панели она упала:

Гаджеты запускаются внутри разделяемого процесса
Sidebar-а, так что моя первая мысль была о том,
что повреждение памяти в процессе вызвало остановку часов и последующее падение.
Для подтверждения этой теории мне надо было проанализировать само крушение
Sidebar-а. Сервис Windows Error Reporting (WER) при падении создает дамп с
сохранением состояния сбойнувшего процесса если вы согласны отправить
Microsoft описание проблемы. Я кликнул на View Details
для определения того, где же хранится дамп:

Последняя ссылка, показанная в окне,
WERD8EE.tmp.mdmp, и является дампом, так что я запустил утилиту

Microsoft Debugging Tools for Windows Windbg
и открыл его. При открытии
Windbg автоматически показывает инструкцию, приведшую к сбою. В моем случае это
была операция копирования в памяти в Msvcrt, Microsoft C Runtime:

В правой части инструкции видно, что целевой адрес копирования это 0. В
случае, если все ресурсы памяти исчерпаны, функция выделения памяти обычно
возвращает 0, так же известный как нулевой указатель (NULL
pointer). По умолчанию это неправильный адрес для процессов
Windows (приложения могут вручную писать/читать память по нулевому
адресу, но обычно это не делается). Тот факт, что Sidebar ссылается на адрес 0
окончательно не означает, что падение было вызвано нехваткой памяти нежели ее
повреждением, но такая ошибка представляется наиболее вероятной.

Я посмотрел на код, вызвавший падение что бы определить
— сам ли Sidebar или один из гаджетов
передал нулевой указатель к процедуре C Runtime.
Открыл Windbg и посмотрел стек:

Ранее я сконфигурировал символьный путь Windbg
на указание на

Microsoft symbol server
, так что Windbg показывал мне имена внутренних
функций Windows, что упростило понимание дампа.
Функции, перечисленные в стеке подразумевают, что перед падением Sidebar
запрашивал версию "package". Я не уверен в каких случаях Sidebar обращается с
такими запросами, но ситуация четко не определял кто виноват — гаджет или сам
сайдбар.

Так что же —
Sidebar-у не хватило памяти? Я начал проверку с переданной памяти (committed
memory), это было наиболее быстро. Общая переданная память (виртуальная
память, для которой зарезервировано место в файле подкачки)
— сумма файлов подкачки и большей части физической памяти. Когда виртуальная
память подходит к концу Windows Vista предупреждает
пользователя списком процессов, потребляющих наибольший объем памяти и
предоставляет возможность уничтожить тех из них, которые занимают больше всего
памяти. Я не видел такого предупреждения, так что я сомневался в таком
предположении, однако открыл в

Process Explorer
диалог System Information для проверки:

Как я и предполагал в системе была масса памяти. В следующую очередь я
посмотрел на использование виртуальной памяти. Виртуальная память, которую
процесс выделяет для хранения своих данных называется
Private Bytes, так что я открыл Process Explorer и
добавил колонку Private Bytes.

На 32-битных Windows процесс по умолчанию может
адресовать до 2 Гб памяти, следовательно самое большое значение
Private Bytes близко к 2 Гб, что мы и видим у
процесса Sidebar с номером 4680. Утечка памяти в
Sidebar-е привела к исчерпанию адресного пространства,
что и вызвало в дальнейшем ошибку с выделением памяти и передачей нулевого
указателя. Я подозревал, что часы остановились при исчерпании доступной памяти и
сам гаджет не смог выделить ресурсов для обновления графики.

Теперь предстояло еще выяснить какой из гаджетов вызвал утечку — возможно это
были часы, а возможно и нет. Сам
Sidebar состоит из двух процессов — один
Sidebar.exe несет гаджеты Windows,
дочерний Sidebar.exe предназначен для сторонних
программ. С этой точки зрения я уже знал, что утечку вызвали именно сторонние
гаджеты, но я не знал какой именно. К сожалению за распределением памяти по
отдельным гаджетам проследить невозможно, так что мне пришлось делать все
вручную.

После рестарта
Sidebar-а я удалил все сторонни гаджеты и начал
добавлять их по одному, оставляя работать на минуту или две. Сам же я наблюдал
за потреблением памяти. Я добавил колонку Private Bytes Delta в Process Explorer,
она показывала изменения в значении Private Bytes. После добавления одного из
гаджетов я начала видеть непрерывный прирост:

Теперь я точно знал виновный гаджет и мог удалить его с чистой совестью.

 

Оригинал:


http://blogs.technet.com/markrussinovich/default.aspx

Читай так же:

История
пропавшей DLL

История
неудавшегося сжатия

Windows
Defender: история одного торможения

Сам себе Руссинович

Оставить мнение

Check Also

Windows 10 против шифровальщиков. Как устроена защита в обновленной Windows 10

Этой осенью Windows 10 обновилась до версии 1709 с кодовым названием Fall Creators Update …