Отладка службы Windows / Хабр

fbdceefbaefdbbdecd Новости

Что нужно для начала отладки

Даю бесплатный совет: пока читаете статью, проделывайте все то, что здесь будет описано, благо есть все для этого.

Что нужно:

Что такое debug

Debug в Intellij IDEA: гайд для новичков - 3

Debug — это процесс отладки (проверки) кода, когда в процессе его выполнения можно остановиться в обозначенном месте и посмотреть за ходом выполнения. Понять, в каком состоянии находится программа в определенном месте.

Это точно так же, как если бы можно было остановить жизнь и посмотреть на всё со стороны.

Почему debug тебе необходим

Давайте сразу проясним для себя: кода без багов не бывает… Так устроена жизнь. Поэтому не стоит сразу раскисать и бросать все, если код работает не так, как мы ожидали.

Debug в Intellij IDEA: гайд для новичков - 2

Но что же делать? Конечно, можно наставить

System.out.println

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

Все-таки можно… и это делают, и делают аккуратно при помощи логирования (можно почитать об этом

).

Но если есть возможность запустить на локальной машине код, лучше использовать

Debug

. Сразу хочу заметить, что в этой статье мы будем рассматривать дебаг проекта внутри Intellij IDEA. Если интересно почитать об удаленном дебаге — вот, пожалуйста,

Выход ssh

ali-4c3275957b8b:~ $ ssh -i ~/.ssh/id_aliyun_rsa [email protected] exit
[email protected]:~ $

Выход sshd

[email protected]:~#$(which sshd) -D
Could not load host key: /etc/ssh/ssh_host_ed25519_key
  C-c C-c
[email protected]:~#

Зачем это всё?


Если вы взялись за написание службы, то встаёт вопрос об её отладке. В интернетах в основном пишут про способ, который заключается в

, про альтернативу которому я и хочу рассказать. Т.к. служба — это не совсем обычный процесс Windows, просто запустить её из Visual Studio у вас не получится.

История 1

Собственно, началось все с того, что пришел баг о том что при некоторых операциях приложение вылетает. Это бывает часто. Баг не захотел воспроизводиться в Debug-версии. Это порой бывает. Поскольку в приложении часть библиотек была написано на C , то первой мыслью было что-то вроде «где-то забыли переменную проинициализировать или что-то в этом духе». Но на деле суть бага крылась в управляемом коде, хотя без неуправляемого тоже не обошлось.

А код оказался примерно следующим:

class Wrapper : IDisposable
{
publicIntPtr Obj {get; privateset;};

    public Wrapper()
{
this.Obj = CreateUnmObject();
}

    ~Wrapper()
{
this.Dispose(false);
}

    protectedvirtualvoid Dispose(bool disposing)
{
if (disposing)
{
}

      this.ReleaseUnmObject(this.Obj);
this.Obj = IntPtr.Zero;
}

    publicvoid Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
}

* This source code was highlighted with Source Code Highlighter.

В принципе, практически каноническая реализация шаблона IDisposable («практически» — потому, что нет переменной disposed, вместо нее обнуление указателя), вполне стандартный класс-обертка неуправляемого ресурса.

Использовался же класс примерно следующим образом:

{
Wrapper wr = new Wrapper();
calc.DoCalculations(wr.Obj);
}

* This source code was highlighted with Source Code Highlighter.

Естественно, что внимательный читатель сразу обратит внимание, что объекта wr надо вызвать Dispose, то есть обернуть все конструкцией using. Но на первый взгляд, на причину падения это не должно повлиять, так как разница будет в том детерминировано ли очистится ресурс или нет.

Но на самом деле разница есть и именно в релизной сборке. Дело в том, что объект wr становится доступным сборщику мусора сразу после начала выполнения метода DoCalculations, ведь больше нет ни одного «живого» объекта, кто на него ссылался бы. А значит wr вполне может(а так оно и происходило) быть уничтожен во время выполнения DoCalculations и указатель, переданный в этот метод становится невалидным.

Если обернуть вызов DoCalculations в using (Wrapper wr = new Wrapper()){…}, то это решит проблему, поскольку вызов Dispose в блоке finally, не даст жадному сборщику мусора «съесть» объект раньше времени. Если же по какой-то причине мы не можем или не хотим вызывать Dispose (к примеру WPF этот шаблон совсем не жалует), то придется вставлять GC.KeepAlive(wr) после вызова DoCalculations.

Реальный код, безусловно, был сложнее и разглядеть в нем ошибку было не так просто, как в примере.

Почему же ошибка проявлялась только в Release-версии, и то запущенной не из-под студии(если присоединить отладчик в процессе выполнения, то ошибка будет повторяться)? Потому что в противном случае для всех локальных ссылочных переменных добавляются якоря, чтобы они доживали до конца текущего метода, сделано это явно ради удобства отладки.

История 2

Жил-был проект, где для доступа к ресурсам использовался менеджер, который по строковому ключу доставал из заданной сборки различного вида ресурсы. С целью облегчения написания кода был написан следующего вида метод:

publicstring GetResource(string key)
{
Assembly assembly = Assembly.GetCallingAssembly();
returnthis.GetResource(assembly, key);
}

* This source code was highlighted with Source Code Highlighter.

После миграции на .Net 4 некоторые ресурсы внезапно перестали находиться. И дело тут опять же в оптимизации релизной версии. Дело в том, что в 4 версии дотнета компилятор может встраивать вызовы в код методов других сборок.

Чтобы «почувствовать разницу» предлагается следующий пример:

  dll1:
publicclass Class1
{
publicvoid Method1()
{
Console.WriteLine(new StackTrace());
}
}

  dll2:
publicclass Class2
{
publicvoid Method21()
{
this.Method22();
}

    publicvoid Method22()
{
(new Class1()).Method1();
}
}

  dll3:
class Program
{
staticvoid Main(string[] args)
{
(new Class3()).Method3();
}
}
class Class3
{
publicvoid Method3()
{
(new Class2()).Method21();
}
}

* This source code was highlighted with Source Code Highlighter.

Если скомпилировать в дебажной конфигурации(или если запускать процесс из-под студии) то получим честный стек вызовов:в ClassLibrary1.Class1.Method1()в ClassLibrary2.Class2.Method22()в ClassLibrary2.Class2.Method21()в ConsoleApplication1.Class3.Method3()в ConsoleApplication1.Program.Main(String[] args)

Если собрать под .Net версии до 3.5 включительно в релизе:в ClassLibrary1.Class1.Method1()в ClassLibrary2.Class2.Method21()в ConsoleApplication1.Program.Main(String[] args)

А под .Net 4 в релизной конфигурации то и вовсе получим:в ConsoleApplication1.Program.Main(String[] args)

Мораль здесь проста — не стоит привязывать логику к стеку вызовов, равно как и удивляться необычному стеку в исключениях в логе релизной версии. В частности, если вы пытаетесь найти причину исключения исключительно по его стеку вызовов, то стоит учитывать, что если стек заканчивается на методе Method1, то в коде оно(исключение) могло быть сгенерировано в одном из небольших методов, которые вызываются в теле Method1.

Так же на всякий случай стоит помнить, что можно запретить компилятору встраивать метод пометив его атрибутом [MethodImpl(MethodImplOptions.NoInlining)], эдакий аналог __declspec(noinline) в VC .

Как начать sshd на переднем конце?

Может действительно увеличена путем изменения сценария запуска или связанных с ними файлов конфигурации-dПараметры. К примеру, на CentOS может быть изменен/etc/sysconfig/sshdДля достижения этой цели.

Но лучшим решением будет использовать параметры командной строки. Это требует SSHD к переднему концу.

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

Root @ localhost: ~ netstat -ltpn # 1. Проверьте, работает ли SSHD
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      978/sshd
tcp        0      0 127.0.0.1:32000         0.0.0.0:*               LISTEN      918/java
 Root @ localhost: ~ Service SSHD Стоп # 2. Пауза SSHD Операция
 Root @ localhost: ~ netstat -ltpn # 3. Подтвердите, что SSHD был закрыт
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:32000         0.0.0.0:*               LISTEN      918/java
 Root @ localhost: ~ $ (какой SSHD) -D # 4. интерфейс запускает SSHD и начать режим отладки
... ...

Как начать отладку варианты?

Оба SSH и SSHD имеют параметры конфигурации и параметры командной строки для инициирования отладки. То же одно и то же, все из которых являютсяLogLevel。

Для конкретного использования элементов конфигурации, пожалуйста, обратитесь кssh_config(5)с участиемsshd_config(5)Отказ Мы рассматриваем только опции командной строки ниже.

Немного теории… обещаю :d

Чтобы начать мало-мальски дебажить, нужно понять, что такое

breakPoint

и разобраться в нескольких горячих клавишах, которые нужны для начала.

BreakPoint

— это специальный маркер, который отображает место или
состояние, на котором нужно остановить приложение.

Поставить breakpoint можно либо нажав левой кнопкой мыши на левую боковую панель, либо кликнув курсором по месту кода и нажав

Ctrl F8

.

Breakpoint’ы бывают трех видов: метка на строку, метка на переменную и метка на метод.

Выглядит это так:

Breakpoint’ы можно удалить, выполнив те же действия, что и при их добавлении.

Бывают ситуации, когда нужно сделать их неактивными (замьютить). Для этого в Debug секции, можно найти значок

Debug в Intellij IDEA: гайд для новичков - 10

, который сделает все breakpoint’ы неактивными.

Чтобы посмотреть, какие уже выставленные breakpoint’ы, можно или зайти в Debug в левом нижнем углу и найти иконку

Debug в Intellij IDEA: гайд для новичков - 11

, или нажать

Ctrl Shift F8Debug в Intellij IDEA: гайд для новичков - 12

Когда зайдем в список breakpoint’ов, увидим:

Debug в Intellij IDEA: гайд для новичков - 13

Здесь есть два preakpoint’a:

  • Bee.java:24 — в классе Bee на 24-й строке
  • Main.java:14 — в классе Main на 14-й строке

Хочу заметить, что при клонировании проекта к себе не будет этих BreakPoint’ов: их нужно выставить самостоятельно!

Также есть секция

Java Exception Breakpoints

. Очень полезная вещь. При помощи ее можно добавить неявный breakpoint, чтобы программа останавливалась перед выбрасыванием любого исключения или какого-то конкретного.

Добавим для RuntimeException неявный breakpoint. Делается это легко: в верхнем левом углу есть плюсик “ ”. Нажимаем на него и выбираем

Java Exceptions BreakpointsDebug в Intellij IDEA: гайд для новичков - 14

В появившемся окне пишем имя исключения, которое нужно добавить, выбираем из предложенного списка и нажимаем

OKDebug в Intellij IDEA: гайд для новичков - 15

На этом ликбез заканчиваем и переходим к практике.

Отладчик

Отладчик – это компьютерная программа, которая позволяет программисту контролировать выполнение программы и проверять ее состояние во время выполнения программы. Например, программист может использовать отладчик для выполнения программы построчно, по ходу проверяя значения переменных.

Возможности отладчика двойственные: способность точно контролировать выполнение программы и возможность просматривать (и при желании изменять) состояние программы.

Ранние отладчики, такие как gdb, были отдельными программами с интерфейсами командной строки, где программисту приходилось вводить загадочные команды, чтобы заставить их работать. Более поздние отладчики (такие как ранние версии Turbo Debugger от Borland) всё еще были автономными, но поставлялись со своими собственными «графическими» интерфейсами для облегчения работы с ними.

Большинство современных IDE, доступных в наши дни, имеют встроенный отладчик, то есть отладчик использует тот же интерфейс, что и редактор кода, поэтому вы можете отлаживать программу, используя ту же среду, которую вы используете для написания кода (вместо того, чтобы переключаться между программами).

Параметры отладки sshd-d

Добавить SSHD-dПараметры могут начать свой режим отладки. Сравнивать

Параметры отладки ssh-v

Дайте командную строку SSH-vОпция может начать свой режим отладки. Мы сравниваем-vРазница между вариантами.

Когда нет опции -V, SSH строго следует обучению «молчание золота»

[email protected]:~$ ssh -i ~/.ssh/id_rsa [email protected] exit
[email protected]:~$

Выход SSH следующим образом, когда существует опция -V

Пошаговое выполнение

Мы собираемся начать изучение отладчиков с изучения некоторых инструментов отладки, которые позволяют нам контролировать выполнение программы.

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

Есть несколько пошаговых команд, которые мы рассмотрим по очереди.

Программа debug

Главная /
Ассемблер /
Для чайников /
Быстрый старт /

ПРИМЕЧАНИЕ
Рисунки на этой странице не отображаются, но вы можете найти их в книге.

Как уже говорилось (см. ВВЕДЕНИЕ),
программа Debug входит в состав Windows. Запустить программу Debug
можно из командной строки или непосредственно из папки, в которой она находится. Чтобы
запустить программу из командной строки, выберите команду из меню ПУСК – ВЫПОЛНИТЬ или
нажмите комбинацию клавиш WIN R (если вы не знаете, что такое комбинация клавиш, см.
книгу Компьютер для чайников).
В открывшемся окне (рис. 1.5) напечатайте слово debug и нажмите клавишу ENTER или щёлкните кнопку ОК.

После этого откроется окно с пустым экраном и чёрточкой в левом верхнем углу,
которая приглашает вас ввести какую-либо команду. Например, чтобы выйти из программы Debug,
напечатайте букву q и нажмите ENTER.

Написать программу, используя Debug, можно не единственным способом, но мы пока
рассмотрим тот, который больше похож на написание программы для
Emu8086.

Чтобы написать уже известную нам программу, используя Debug, сделаем следующее
(подразумевается, что Debug вы уже запустили, и увидели черный экран с маленькой мигающей
черточкой в левом верхнем углу).

Введем букву «а» (напоминаю в последний раз – все команды вводятся на
английском языке) и нажмем ENTER.

Затем введем программу, нажимая ENTER в конце каждой строки:

 
0B72: 0100 MOV AH, 02
0B72: 0102 MOV DL, 41
0B72: 0104 INT 21
0B72: 0106 INT 20
0B72: 0108

Результат будет примерно таким, как показано на рис. 1.6.

ПРИМЕЧАНИЕ 1
Обратите внимание, что все числовые значения пишутся без буковки h в конце. Это потому,
что Debug работает только с шестнадцатеричными числами, и ему не надо объяснять,
в какой системе исчисления вводятся данные.

ПРИМЕЧАНИЕ 2
После ввода команды -а, появляются символы: 0B72: 0100. В вашем случае первые четыре
символа могут быть другими, но нас они пока не интересуют. А как вы думаете, что означает
число 0100? Помните директиву ORG 100h (см. раздел
Emu8086)?
Вот-вот – это адрес, с которого начинается выполнение программы. То есть в память с
этим адресом заносится первая команда программы (для файлов СОМ). Каждая команда занимает
2 байта, поэтому следующий адрес будет 0102 и т.д.

Сами команды мы уже знаем (см. раздел
Emu8086),
поэтому описывать их здесь не будем.

Программа написана – нужно проверить ее работу. Нажмём ENTER ещё раз, чтобы на экране
появилась чёрточка, которая говорит о том, что можно вводить команду для Debug. Затем
введем команду g (от английского «GO») и нажмем клавишу ENTER. На экране увидим следующее:

-g
A
Программа завершилась нормально
-

Здесь A – та самая буква, которая выводится на экран в результате работы программы.
Затем идёт сообщение о нормальном завершении программы (оно может отличаться в зависимости
от версии Debug).

А теперь, если интересно, можно проверить программу в пошаговом режиме, то есть
понаблюдать, как выполняются команды одна за другой. Для этого придется по новой
набрать текст программы (не забудьте сначала ввести команду а), затем:

Введем команду t и нажмем клавишу ENTER. Увидим нечто вроде этого:

AX=0200  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0B72  ES=0B72  SS=0B72  CS=0B72  IP=0102  NV UP EI PL NZ NA PO NC
0B72:0102 B241		MOV	DL,41

Это есть ни что иное, как состояние регистров процессора после выполнения первой
строки программы. Как вы можете видеть, в регистр АН записалось число 02. В нижней
строке находится адрес команды и сама команда, которая будет выполняться следующей.

Снова введем команду t и нажмем клавишу ENTER. Увидим следующее:

AX=0200  BX=0000  CX=0000  DX=0041  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0B72  ES=0B72  SS=0B72  CS=0B72  IP=0104  NV UP EI PL NZ NA PO NC
0B72:0104 CD21		INT	21

Команда MOV DL, 41, как ей и полагается, записала в регистр DL число 41.

Снова введем команду t и нажмем клавишу ENTER. Увидим следующее:

AX=0200  BX=0000  CX=0000  DX=0041  SP=FFE8  BP=0000  SI=0000  DI=0000
DS=0B72  ES=0B72  SS=0B72  CS=0347  IP=0225  NV UP EI PL NZ NA PO NC
0347:0225 80FC4B	CMP	AH,4B

Команды CMP AH,4B нет в нашей программе. Наша программа завершила свою работу.
Мы можем долго еще вводить команду t – нам будут выдаваться состояния регистров.
Почему это происходит, нам пока не интересно. Лучше введем команду g и нажмем клавишу ENTER,
таким образом окончательно выполним нашу программу, и увидим то, что мы уже видели.

Программа написана и проверена. Но как сделать ее самостоятельной, то есть как создать
файл СОМ? Ведь то, что мы сделали, работает только с помощью Debug. Чтобы создать
исполняемый файл, нужно ответить на несколько вопросов:

  1. Какого размера будет наш файл? Выполнение программы начинается с адреса 0100h,
    а последняя строка в программе содержит адрес 0108h. Это значит, что размер файла
    будет 8 байт (108h – 100h = 8).
  2. Как мы назовем наш файл? А хоть как. Однако, рекомендуется давать файлам английские
    имена, в которых содержится не более 8 символов (DOSу так приятнее работать). Назовем,
    например, debug_1.com

А теперь выполним следующие действия:

  1. Снова напишем нашу программу (тренируйтесь, тренируйтесь…).
  2. Запишем в регистр СХ размер файла. Для этого введем команду r cx и нажмем ENTER. Затем введем размер файла (8 байт) и нажмем ENTER.
  3. Введем команду n, затем один пробел и имя файла. Нажмем ENTER.
  4. И, наконец, введем команду w и нажмем ENTER.

В результате всех этих действий на экране появится следующая информация (см. также рис. 1.7):

-r cx
СХ 0000
:8
-n debug_1.com
-w
Запись: 00008 байт
-

Если вы работаете в режиме эмуляции DOS из под WINDOWS, то файл debug_1.com
сохранится на рабочий стол, либо в папку текущего пользователя. Это зависит от
версии и/или настроек WINDOWS. Теперь его можно запустить как обычную программу.
Если в указанных папках вы не нашли этот файл, то найдите его через поиск файлов.
Ну а если вы не знаете, как это сделать, см. книгу Компьютер для чайников.

Чувствую, что мы уже устали. Выход из Debug осуществляется командой q.

Набравшись сил и терпения, изучим еще одну опцию Debug – дизассемблер. С его помощью
можно дизассемблировать какой-нибудь СОМ-файл (то есть выполнить действие, обратное
ассемблированию – преобразовать исполняемый файл в исходный код на языке ассемблера).
Допустим, у вас есть программка, написанная не вами – ее исходный код вы не знаете,
а посмотреть очень хочется. Для этого и существует дизассемблер.

Итак, программа Debug у нас закрыта. Набираем в командной строке:

debug debug_1.com

(где debug_1.com – это имя файла, который мы хотим дизассемблировать) и нажимаем ENTER.

ПРИМЕЧАНИЕ
Если программа не запустилась, значит нужно указать полный путь к ней, например

C:WINDOWSCOMMANDdebug debug_1.com

Если же программа запустилась, но выдала ошибку (например: Ошибка 1282 или «Файл не найден»),
то нужно указать полный путь к файлу, например:

C:WINDOWSCOMMANDdebug C:MYPROGdebug_1.com

Если и это не помогло, то, возможно, вы всё-таки где-то допустили ошибку в пути или
путь не соответствует требованиям DOS. В таком случае лучше поместить программу в
корень диска С, откуда она гарантированно загрузится по пути «C:debug_1.com».

Если Debug запустилась без сообщений об ошибках, то вводим команду u и нажимаем ENTER.
Вот что мы увидим (примерно, см. также рис 1.8):

-u
0BC6:0100 B402		MOV	AH, 02
0BC6:0102 B241		MOV	DL, 41
0BC6:0104 CD21		INT	21
0BC6:0106 CD20		INT	20
0BC6:0108 56		PUSH	SI
0BC6:0109 2E		CS:
0BC6:010A 8A04		MOV	AL, [SI]
0BC6:010C 0AC0		OR	AL, AL
0BC6:010E 741A		JZ	012A
0BC6:0110 3C3A		CMP	AL, 3A
0BC6:0112 750D		JNZ	0121
0BC6:0114 2E		CS:	
0BC6:0115 807C0100	CMP	BYTE PTR [SI 01], 00
0BC6:0119 7506		JNZ	0121
0BC6:011B 2E		CS:
0BC6:011C C60400	MOV 	BYTE PTR [SI], 00
0BC6:011F EB09		JMP 	012A
-

Посмотрите на первые четыре строки. Узнаете? Это наша программа. Остальные строки
нас не интересуют (это инструкции, оставшиеся от программ или данных, отработавших
до запуска Debug). Ну а если мы рассматриваем незнакомый файл, как узнать, где
кончается программа и начинается «мусор»? Ориентировочно это можно сделать по размеру
файла (для очень маленьких программ). Размер можно посмотреть в свойствах файла.
Только следует учитывать, что в свойствах файла размер дан в десятичной форме, а
Debug нам выдает шестнадцатеричные адреса. Поэтому придется перевести десятичное число
в шестнадцатеричное.

Есть еще вариант (который тоже не всегда приемлем) – найти в полученном списке строку,
содержащую команду выхода из программы (INT 20).

Если программа большая, то список ее команд не поместится на экран. Тогда снова вводим
команду u и нажимаем ENTER. И так до конца программы.

Возможно, вы не увидите на экране свою программу. Это может быть либо из-за того,
что программа почему-то не загрузилась, либо по причине несоответствия адресов.
Будьте внимательны: обращайте внимание на адреса памяти, которые указаны в левой колонке.
Наша программа начинается с адреса 0100. Если адрес другой, то это, соответственно,
не наша программа.

Способ №1 (подключение отладчика)

  1. Запустите службу с помощью консоли управления службами Windows.
  2. В Visual Studio выберите Tools → Connect To Process в появившемся диалоговом окне выберите имя процесса службы и нажмите кнопку Attach

После этого можно расставлять точки останова и отлаживать службу.

У этого способа есть недостаток: без дополнительных ухищрений не получится отладить код, находящийся в обработчике

OnStart

Способ №2 (подключение отладчика из исходного кода)

В код модуля

program.cs

, сразу после начала метода

Main()

добавляем следующее:

#if DEBUG
System.Diagnostics.Debugger.Launch();
#endif


Этот код подключает отладчик к процессу и компилируется только в режиме

DEBUG

. Теперь для отладки службы её нужно запускать не из Visual Studio, а с помощью консоли управления службами (или команды

net start

). Сразу после запуска появится диалоговое окно выбора отладчика:

Выбираете запущенный экземпляр Visual Studio, нажимаете

Yes

и наслаждаетесь отладкой!

Способ №3 (запуск с параметрами командной строки)

предложил

Есть еще способ — предусматривать возможность запуска службы как консольного приложения. Например, в командной строке передавать /console, и если этот флаг установлен, стартовать приложение как консольное, если нет — как службу.

Преимущества такого подхода:Очень просто отлаживать, по сути дела, как обычное консольное приложение. В консоль можно выводить отладочную информацию

Спасибо komr за помощь в отладке текста 🙂

Установка службы

При попытке запуска вам будет показано сообщение, что, мол, служба запуститься не может и вам нужно использовать

installutil.exe

для её установки.


Для установки службы вам потребуется консоль Visual Studio, которая находится по пути

Пуск → Программы → Visual Studio 2008 → Visual Studio Tools → Visual Studio 2008 Command Prompt

(в зависимости от версии установленной VS путь может отличаться)

После запуска консоли переходим в директорию, в которую собирается ваша служба в режиме

Debug

и устанавливаем её:

installutil.exe /i <имя вашей сборки со службой>

Более вам

installutil.exe

не потребуется. Для удобства запускаем консоль управления службами Windows:

services.msc

Теперь консоль Visual Studio можно закрыть.


Переходим к самому интересному 🙂

Шаг назад

Некоторые отладчики (такие как Visual Studio Enterprise Edition и GDB 7.0) представили возможность пошагового выполнения, обычно называемую шагом назад или обратной отладкой. Цель шага назад – отмотать последний шаг назад, чтобы вы могли вернуть программу в предыдущее состояние. Это может быть полезно, если вы перешагнули цель, или если вы хотите повторно проверить только что выполненную инструкцию.

Шаг с выходом (step out)

В отличие от двух других пошаговых команд, шаг с выходом (step out) не просто выполняет следующую строку кода. Вместо этого он выполняет весь оставшийся код функции, которая выполняется в настоящее время, а затем возвращает управление вам, когда будет выполнен возврат из функции.

Для пользователей Visual Studio


В Visual Studio команду шаг с выходом можно выполнить через меню Отладка (Debug) → Шаг с выходом (Step Out), или нажав комбинацию клавиш Shift F11.

Давайте посмотрим на пример этого, используя ту же программу, что и выше:

#include <iostream>
 
void printValue(int value)
{
    std::cout << value << 'n';
}
 
int main()
{
    printValue(5);
 
    return 0;
}

Выполните команды шаг с заходом, пока не окажетесь внутри функции printValue с маркером выполнения в строке 4.

Рисунок 8 Положение маркера в начале выполнения функции printValue
Рисунок 8 – Положение маркера в начале выполнения функции printValue

Затем выполните шаг с выходом. Вы заметите, что в окне вывода появится значение 5, и отладчик вернет вам управление после завершения функции (в строке 10).

Рисунок 9 Положение маркера после выполнения шага с выходом в функции printValue
Рисунок 9 – Положение маркера после выполнения шага с выходом в функции printValue

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

Шаг с заходом (step into)

Команда шаг с заходом (step into) выполняет следующую инструкцию в обычном пути выполнения программы, а затем приостанавливает выполнение программы, чтобы мы могли проверить состояние программы с помощью отладчика. Если выполняемый оператор содержит вызов функции, шаг с заходом заставляет программу перескакивать в начало вызываемой функции, где она приостанавливается.

Давайте посмотрим на очень простую программу:

#include <iostream>
 
void printValue(int value)
{
    std::cout << value << 'n';
}
 
int main()
{
    printValue(5);
 
    return 0;
}

Давайте отладим эту программу, используя команду шаг с заходом.

Сначала найдите и затем выполните команду отладки шаг с заходом один раз.

Для пользователей Visual Studio


В Visual Studio к команде шаг с заходом (step into) можно получить доступ через меню Отладка (Debug) → Шаг с заходом (Step Into), или нажав клавишу F11.

Для других компиляторов


Если вы используете другую среду IDE, вы, вероятно, найдете команду step into в меню Debug (Отладка) или Run (Выполнить).

Когда ваша программа не запущена и вы выполняете первую команду отладки, вы можете увидеть, что происходит несколько вещей:

  • При необходимости программа перекомпилируется.
  • Программа начинает выполняться. Поскольку наше приложение является консольной программой, должно открыться окно консоли. Оно будет пустым, потому что мы еще ничего не выводили.
  • В вашей IDE могут открываться некоторые диагностические окна, которые могут иметь такие названия, как «Diagnostic Tools» (средства диагностики), «Call Stack» (стек вызовов) и «Watch» (наблюдение). Некоторые из них мы рассмотрим позже – пока вы можете их игнорировать.

Шаг с обходом (step over)

Как и шаг с заходом, команда шаг с обходом (step over) выполняет следующую инструкцию в обычном пути выполнения программы. Однако в то время как шаг с заходом будет входить в вызовы функций и выполнять их построчно, шаг с обходом выполнит всю функцию без остановки и вернет вам управление после выполнения этой функции.

Для пользователей Visual Studio


В Visual Studio к команде шаг с обходом (step over) можно получить доступ через меню Отладка (Debug) → Шаг с обходом (Step Over), или нажав клавишу F10.

Давайте посмотрим на пример, в котором мы делаем шаг с обходом вызова функции printValue:

#include <iostream>
 
void printValue(int value)
{
    std::cout << value << 'n';
}
 
int main()
{
    printValue(5);
 
    return 0;
}

Сначала используйте команду шаг с заходом, пока маркер выполнения не окажется в строке 10:

Рисунок 7 Положение маркера перед выполнением функции printValue
Рисунок 7 – Положение маркера перед выполнением функции printValue

Теперь выполните шаг с обходом. Отладчик выполнит функцию (которая выводит значение 5 в окно консоли), а затем вернет управление вам в следующей инструкции (строка 12).

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

Шаги по ssh

ssh -vvv [email protected]_host

Исследовать счастье.

Шагнули слишком далеко

При пошаговом выполнении программы вы обычно можете шагать только вперед. Очень легко случайно перешагнуть то место, которое вы хотели исследовать.

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

Этапы sshd

# 1. Проверьте, работает ли SSHD
netstat -ltpn
 # 2. Закройте SSHD
service sshd stop
 # 3. Проверьте, был ли закрыт SSHD
netstat -ltpn
 # 4. Запустите передний конец и запустите режим отладки
 $ (Какая SSHD) -D -D-# -D, чтобы убедиться, что SSHD работает на переднем конце
 # 5. Тест, тест, проверка ...
 # 6. Перезапуск SSHD
service sshd start

Подведем итог

За эту статью мы разобрались, что:

  • работы без ошибок не бывает и дебаг — это отличный способ их решить;
  • что такое breakpoint и какой он бывает;
  • как настроить exception breakpoint;
  • как проводить навигацию в режиме дебага.

Вместо заключения

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

Оцените статью
Huawei Devices
Добавить комментарий