Autoexp.dat или отображение сложных типов в отладчике Visual Studio

27 Апр
2012

В данном топике расскажу как сделать корректное отображение собственных типов данных в отладчике на Visual Studio (2005–2010).
То есть мы хотим заменить стандартное отображение для типа std: pair
image
На более информативные для нас данные, необходимые при отладке сложных приложений, и стало, например, вот таким:
image

Реализация — под катом.


За отображение данных во встроенном отладчике Visual Studio (версий 2005, 2008, 2010) отвечает файл autoexp.dat, располагающийся по адресу:

«C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\autoexp.dat».

Здесь не собираюсь выкладывать полный туториал по правилам модификации указанного файла, а приведу частный пример его использования и пару примеров, на основе которого у вас будет достаточно информации чтобы самим решать подобные задачи.

Итак, допустим у нас есть следующий код.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 
 
        #include <cstdio>
        #include <map>
        #include <windows.h>
 
        class Inner {
        private:
            std::string *raw;
        public:
            void Init(std::string a) {
                raw = new std::string(a);
        };
        };
 
        class MyClass {
        public:
            Inner inn;
        };
 
        std::multimap <DWORD, MyClass> all;
 
        int main() {
            MyClass a,b,c;
 
            char c5 = 5;
            std::string s5;
            s5.push_back(c5);
            a.inn.Init(s5);    //хранится 1-байтовое значение
 
            DWORD nt = 0x12345678;
            b.inn.Init(std::string((char*)&nt,4)); //храним unsigned long как строку 4х байт...
 
            c.inn.Init("string");    //обычная строка
 
            all.insert(std::make_pair(0,a));
            all.insert(std::make_pair(1,b));
            all.insert(std::make_pair(2,c));
 
            return 0; //отладочная точка останова
        }

Делая точку останова на «return 0» мы видим в отладчике следующее:



На первой картинке поста сразу видно, что отображение содержания std: string происходит так, как нам нужно, при условии, что там лежит строка.
За его реализацию отвечает следующий код, находящийся в autoexp.dat:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
;------------------------------------------------------------------------------
;  std::string/basic_string
;------------------------------------------------------------------------------
std::basic_string<char,*>{
    preview     ( #if(($e._Myres) < ($e._BUF_SIZE)) ( [$e._Bx._Buf,s]) #else ( [$e._Bx._Ptr,s]))
    stringview  ( #if(($e._Myres) < ($e._BUF_SIZE)) ( [$e._Bx._Buf,sb]) #else ( [$e._Bx._Ptr,sb]))
    children
    (
        #if(($e._Myres) < ($e._BUF_SIZE))
        (
            #([actual members]: [$e,!] , #array( expr: $e._Bx._Buf[$i], size: $e._Mysize))
        )
        #else
        (
            #([actual members]: [$e,!],  #array( expr: $e._Bx._Ptr[$i], size: $e._Mysize))
        )
    )
}

Путем чтения отсутствующей документации и анализа файла autoexp.dat, становится ясно, что:
  • preview — отвечает за отображение заголовка типа данных
  • stringview — его текстовое представление в окне просмотра текста, появляющемся по
  • children — отвечает за отображение элементов в раскрывающегося поддереве

Поэтому в данном топике нам достаточно править preview для наших типов данных. А именно — «вытащить» значение .inn.raw «наверх».
Для этого в файле autoexp.dat создадим отладочное отображение пары std: pair<unsigned long const ,MyClass> — основного типа списка.
Для этого идем вглубь и вытащим наверх интересующий нас его внутренний элемент .second путем дописывания в начало autoexp.dat (после заголовка раздела [Visualizer]) следующий код
1
2
3
4
5
6
 
std::pair<unsigned long const ,MyClass> {
    preview (
        [$e.second]
    )
}

Получаем:



Это общее представление класса MyClass, отображаемое отладчиком по умолчанию. Нас интересует элемент .inn. Дописываем в autoexp.dat:
1
2
3
4
5
MyClass {
    preview (
        [$e.inn]
    )
}

В отладчике видим



Далее добавляя
1
2
3
4
5
Inner {
    preview (
        [$e.raw]
    )
}

У нас получилось



Теперь хочется отобразить типы данных, хранящиеся в std: string такими, какие они есть на самом деле, а не текстом.
(Здесь сразу приведу финальный вариант, потому как на его работоспособность влияет не только количество скобочек и символов #, но и переносы строк…).
Добавляем в autoexp.dat
1
2
3
4
5
6
7
8
Inner {
    preview (
        #switch ($e.raw->_Mysize)
        #case 1 ( $e.raw->_Bx._Buf[0] )
        #case 4 (*(unsigned long*) $e.raw->_Bx._Buf)
        #default ([$e.raw])
    )
}

И получаем полностью удовлетворяющий нас результат



Этим мы экономим во времени блуждания по std: multimap и более сложных структурах в поисках интересующих нас данных.

Далее представлен пример отображения при решении задачи «в каком элементе у нас лежит НЕ текст?!».

До изменений было:


Стало:


*полностью добавленный фрагмент кода в autoexp.dat представлен здесь
По материалам Хабрахабр.



загрузка...

Комментарии:

Наверх