Как работает "Редактировать и продолжить" в Visual Studio?
Я всегда считал, что это очень полезная функция в Visual Studio. Для тех, кто не знает об этом, он позволяет вам редактировать код во время отладки работающего процесса, перекомпилировать код, пока двоичный файл еще работает, и продолжать беспрепятственно использовать приложение с новым кодом, без необходимости перезапустите его.
Как реализована эта функция? Если код, который я изменяю, находится в DLL, загруженной приложением, приложение просто выгружает DLL и перезагружает ее снова? Мне кажется, что это может привести к проблемам нестабильности, поэтому я предполагаю, что это будет умнее, чем это. Есть идеи?
3 ответа
Насколько я понимаю, когда приложение компилируется с включенной поддержкой редактирования и продолжения, компилятор оставляет дополнительное пространство вокруг функций в двоичном изображении, что позволяет добавлять дополнительный код. Затем отладчик может скомпилировать новую версию функции, заменить существующую версию (при необходимости используя пробел), исправить стек, установить указатель инструкций и продолжить работу. Таким образом, вам не нужно исправлять указатели прыжка, если у вас достаточно отступов.
Обратите внимание, что Edit и Continue обычно не работают с кодом в libs/dll, а только с основным исполняемым кодом.
Я предполагаю, что он перекомпилирует приложение (и для небольших изменений это не будет означать, что его придется перекомпилировать). Затем, поскольку Microsoft создает как компилятор, так и отладчик, они могут дать гарантии о том, как устроена память и тому подобное. Таким образом, они могут использовать API отладки для перезаписи сегментов кода новыми, если изменения достаточно малы.
Если изменения перенаправляют на совершенно новый код, он, очевидно, может быть загружен в память в стиле, аналогичном DLL.
У Microsoft также есть механизм "горячих патчей". Функции имеют 2-байтовую безоперационную инструкцию, обычно что-то вроде "mov edx, edx" перед любым реальным кодом. Это позволяет им перенаправить выполнение функции чисто. Это также может быть вариантом.
Главное, что нужно помнить, это то, что приложение не "работает", все его потоки находятся в остановленном состоянии. Таким образом, что касается процесса, любые модификации, сделанные отладчиком, являются полностью атомарными.
Конечно, это все домыслы;)
Я предполагаю, что все объекты выровнены по границе памяти размером 4096 байт. Так что, если вы сделаете небольшие изменения в некотором коде, тогда объекты будут по-прежнему в этих границах и, следовательно, будут работать как прежде
У меня были случаи, когда изменение пары строк приводило к полной перекомпиляции и связыванию, а в других случаях достаточно эффективный рефакторинг функции.