Вопрос или проблема
Найдите адрес статического члена класса C++ с помощью WinDbg.
Я не имею опыта работы с WinDbg и пытаюсь установить точку прерывания данных (ba) на статической переменной-члене в приложении C++ Win32, чтобы увидеть, когда она повреждается из-за непреднамеренных записей. Назовем ее MyClass::m_StaticData. Я понимаю, что сначала мне нужно найти адрес памяти MyClass::m_StaticData. Однако я не уверен, как найти адрес статической переменной-члена. Я нашел команды для локальных переменных (dv) и экземпляров классов (dt), но ничего не нашел для статических переменных.
Рассмотрим следующий код на C++:
class Box {
public:
static int objectCount;
Box(double l = 2.0, double b = 2.0, double h = 2.0) {
length = l;
breadth = b;
height = h;
objectCount++;
}
double Volume() {
return length * breadth * height;
}
static int getCount() {
return objectCount;
}
private:
double length;
double breadth;
double height;
};
int Box::objectCount = 0;
int main(void) {
Box Box1(3.3, 1.2, 1.5);
return 0;
}
Некоторые компиляторы ведут себя по-разному, но MSVC скомпилирует приведенный выше код и сохранит статические переменные вашего класса внутри сегмента .data бинарного файла PE32, вы можете увидеть, каким образом они ссылаются, и мы можем подтвердить, где они хранятся.
Вам нужно будет искать перекрестные ссылки в скомпилированной версии вашего кода, чтобы получить относительный адрес, где переменная выделяется при инициализации. Я не знаю, что это можно легко сделать только с помощью WinDbg, поэтому, взглянув на самый первый смещение кода, которое ссылается на вашу статическую переменную, вы получите RVA вашей переменной, а затем сможете установить там точку прерывания доступа к данным.
Ответ или решение
Для того чтобы найти адрес статического члена класса (в данном случае MyClass::m_StaticData
) и установить на него точку останова данных (data breakpoint) с помощью WinDbg, необходимо выполнить несколько шагов. Рассмотрим это на примере кода, который был предоставлен:
class Box {
public:
static int objectCount;
Box(double l = 2.0, double b = 2.0, double h = 2.0) {
length = l;
breadth = b;
height = h;
objectCount++;
}
double Volume() {
return length * breadth * height;
}
static int getCount() {
return objectCount;
}
private:
double length;
double breadth;
double height;
};
int Box::objectCount = 0;
int main(void) {
Box Box1(3.3, 1.2, 1.5);
return 0;
}
Шаги для нахождения адреса статического члена и установки точки останова:
-
Скомпилируйте проект в режиме отладки: Убедитесь, что ваш проект скомпилирован с включенными отладочными символами (например, используйте флаг
/Zi
в MSVC). -
Запустите ваш приложение в WinDbg: Откройте WinDbg и подключитесь к вашему работающему приложению.
-
Загрузите символы: Убедитесь, что символы загружены корректно. Используйте команду
!sym noisy
, чтобы отладчик выводил дополнительные сообщения о загрузке символов. Затем выполните команду.reload
для перезагрузки символов. -
Определите адрес статического члена:
- Вам нужно будет узнать, где именно в памяти находится статический член
objectCount
. Используйте командуx
для поиска:x Box::objectCount
- Если все сделано правильно, WinDbg выведет информацию о вашем статическом члене в формате, например:
01234ABC Box::objectCount
Здесь
01234ABC
будет адресомobjectCount
.
- Вам нужно будет узнать, где именно в памяти находится статический член
-
Установка точки останова данных: Как только вы узнали адрес статического члена, вы можете установить точку останова данных. Используйте команду
ba
:ba w4 01234ABC
Здесь
w4
указывает на то, что вы хотите установить точку останова на запись 4-байтного значения. - Запуск и диагностика: Запустите ваше приложение, и как только произойдет запись в
objectCount
, выполнение программы остановится, и вы сможете исследовать стек вызовов и текущее состояние программы для диагностики проблемы.
Дополнительные советы:
- Используйте команду
!address
для отображения информации о памяти, если вам нужно больше информации о том, как работает память в вашем приложении. - Опционально, вы можете использовать команду
.data
для получения доступа к сегментам данных, если потребуется больше информации о других статических и глобальных переменных.
Таким образом, следуя вышеизложенным шагам, вы сможете найти адрес статического члена класса и установить на него точку останова в WinDbg для дальнейшего анализа.