Эта статья является продолжением статьи еще в 2014 году.
Напомню, о чем мы говорили в предыдущей статье .
Какую проблему мы решим?
Пишем программное обеспечение на языке С++ , в окружающей среде Визуальная Студия 2015 .Естественно, в нашем проекте есть пользовательские типы данных.
В качестве примера таких типов могу привести класс МбТвердый .
Этот класс является частью математическое ядро C3D и представляет собой абстракцию твердого тела.
Тело описывается ребрами, грани какими-то поверхностями и т. д. Т.
е.
Структура класса довольно сложная, и в процессе отладки собственных алгоритмов хотелось бы визуально оценить, какое тело представляет собой результат на данный момент. Картинка из предыдущей статьи.
В качестве примера пользовательского класса здесь используется класс сегмента линии.
Для решения этой проблемы было написано расширение для VisualStudio. Здесь нет ничего интересного, ссылки есть в предыдущей статье.
Но возникла проблема — как расширение VisualStudio может получить данные из адресного пространства (другого) отлаживаемого процесса? Для простых типов данных, таких как массивы, все не так уж и сложно, и Microsoft даже подготовила пример для этого.
станд::вектор .
И в нашем случае МбТвердый В нем есть впечатляющая иерархия наследования и большое количество полей данных.
Изменение пользовательских типов
В предыдущей статье было предложено инвазивное решение этой проблемы.Поле маркера добавляется в каждый пользовательский класс (который мы хотим визуализировать во время отладки).
И в каждом неконстантном методе класса добавляется код для сериализации данных класса в Общая память .
Поле маркера хранит адрес в Общая память , где мы сохранили данные класса.
В момент отладки при просмотре содержимого интересующей нас переменной расширение VisualStudio находит поле маркера и десериализует данные из Общая память , а потом как-то визуализирует полученные данные.
По понятным причинам такое решение на практике неприменимо.
Особенно, если у нас нет доступа к исходному коду классов, которые мы хотим отладить таким способом.
Ничего лучшего в то время придумать не удалось, и эта тема заглохла на несколько лет.
Сервер в пользовательском процессе
И вот недавно пришла идея написать простой сервер, который будет жить в пользовательском процессе в отдельном потоке и отвечать на запросы, поступающие от нашего расширения VisualStudio. Для сервера за основу был взят проект Microsoft C++ REST SDK .Этот проект позволил мне быстро написать собственный http-сервер, который принимает GET-запросы и возвращает описание экземпляра пользовательского класса в формате json. Напомню, что нас интересует визуальное представление экземпляров классов.
МбТвердый (твердые).
Запрос к серверу передает адрес переменной в адресном пространстве отлаживаемого процесса.
Т.
к.
сервер живет в одном процессе, он легко может получить доступ к данным по запрошенному адресу.
Сервер, получив адрес экземпляра класса, приводит этот указатель к типу МбТвердый* .
Далее сервер создает аппроксимацию этого тела в виде полигональной сетки.
Сериализует вычисленные вершины и индексы треугольников в json и отправляет ответ. На стороне VisualStudio расширение получает ответ, десериализует данные и рисует полученную полигональную сетку в окне VisualStudio. В результате расширению в VisualStudio даже не нужно знать структуру пользовательских данных, ему достаточно уметь отправлять правильные GET-запросы, десериализовать ответ и рисовать треугольники в окне VisualStudio. Сервер можно расширить.
Таким способом можно отлаживать любые пользовательские классы, которые могут быть представлены в виде полигональной сетки или набора отрезков линий, а расширение VisualStudio может их визуализировать:
Более того, таким образом мы даже можем отправлять запросы на наш сервер из браузера и визуализировать данные процесса с помощью WebGL.
Я сделал простой демонстрационный пример.
Давайте запустим наше приложение.
Открываем страницу примера в браузере, вводим адрес переменной на странице, отправляем запрос на сервер и рисуем ответ. Не знаю, зачем это может быть нужно, но штука классная
Возрождение сервера
Все было бы хорошо.Но есть одна проблема.
При достижении точки останова студия останавливает все потоки пользовательского процесса.
В результате наш сервер также останавливается и не может отвечать на запросы.
Чтобы обойти эту проблему, воспользуемся следующим костылем: текущий поток, в котором сработала точка останова, замораживается, и запускается пользовательский процесс.
В этот момент наш сервер оживает и расширение отправляет ему запрос с адресом интересующей нас переменной.
После получения ответа пользовательский процесс снова приостанавливается, а текущий поток для отладчика устанавливается на исходный поток, в котором была достигнута точка останова.
Пользователю кажется, что ничего не произошло и выполнение программы остановилось в точке останова.
В коде расширения VisualStudio этот костыль выглядит так.
Была достигнута точка останова.
Пользователь запрашивает данные для интересующей переменной.
На этом этапе мы останавливаем текущий поток и запускаем отладчик:
Отправляем запрос на сервер.if (dte.Debugger.CurrentMode != EnvDTE.dbgDebugMode.dbgBreakMode) return; currentThread = dte.Debugger.CurrentThread; currentThread.Freeze(); dte.Debugger.Go(false);
Мы получаем ответ. Останавливаем процесс и размораживаем наш поток:
if (dte.Debugger.CurrentMode == EnvDTE.dbgDebugMode.dbgBreakMode)
return;
dte.Debugger.Break();
if (currentThread != null)
{
currentThread.Thaw();
dte.Debugger.CurrentThread = currentThread;
}
Все! Мы получили данные с сервера и отрисовали их в окне VisualStudio. Выполнение программы происходит на исходной точке останова.
В заключение хотелось бы отметить, что я до сих пор не понимаю тех побочных эффектов, которые порождает такой подход. Буду рад, если вы поделитесь своими мыслями в комментариях к этой статье.
Теги: #C++ #отладка #Visual Studio #расширения #microsoft #c3d #c3dkernel #c3dtoolkit #C++ #Visual Studio #отладка #Windows Development
-
Как Выбрать Ноутбук – Что Есть В Наличии?
19 Oct, 24 -
Голосовое Меню Своими Руками
19 Oct, 24 -
О Системах Контроля Версий
19 Oct, 24 -
Выбор Vr-Шлема
19 Oct, 24 -
Легкие Браузеры
19 Oct, 24 -
Оптимизация Производительности Netapp Fas
19 Oct, 24