Sign in Join
Wiki copytemporary

Creating a Backtrace with GDB/ru: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## Причины для создания обратной трассировки
22
33### Отчеты об ошибках
44
55Файлы обратной трассировки могут быть очень полезны при отправке отчетов об ошибках. Они, несомненно, повысят вероятность того, что ошибка будет исправлена раньше.
66
77### Помоги себе найти проблему
88
99Обратная трассировка может действительно облегчить поиск проблемы с вашей собственной программой. Часто проблема выявляется сразу.
1010
1111### Это просто весело!!!
1212
1313Хорошо, это может быть преувеличением, но делать обратную трассировку просто весело!
1414
1515Если серьезно, если вы можете придумать другую причину создания обратной трассировки, добавьте ее сюда.
1616
1717## Создание Backtrace
1818
1919> **Note:** **Mac-пользователям** следует использовать *lldb* вместо *gdb*.
2020
2121Чтобы создать обратную трассировку с помощью [[GDB]] (Gnu DeBugger):
2222
23231. У вас должна быть программа [GDB](http://www.gnu.org/software/gdb/gdb.html). Она доступна на большинстве установленных ОС-*nix. Если вы скачали версию fpc или Lazarus для Windows, GDB уже включен в поставку. В Lazarus он установлен, как отладчик, по умолчанию. Посмотрите в Tools (Сервис) -\> Options (Параметры) -\> Debugger (Отладчик) -\> General Tab (Общие). Путь по умолчанию для GDB в Windows: c:\lazarus\mingw\bin\gdb.exe.
24242. GDB должен быть прописан в переменной окружения PATH. Если это Windows, из командной строки введите (пример): установите PATH =% PATH%; set PATH=%PATH%;c:\lazarus\mingw\bin\\
25253. Программа, которую вы хотите отладить, ДОЛЖНА иметь отладочную информацию, включенную в исполняемый файл. Если вы используете "strip", "upx", компилируете с "Xs" или использовали какой-либо другой exe-упаковщик, это не сработает!
2626
2727------------------------------------------------------------------------
2828
2929Прим.перев.: если вы используете транковые svn-сборки FPC для Windows, то после компиляции gdb.exe в них отсутствует.Его необходимо скопировать (вместе с некоторыми другими утилитами) из папки *\<Stable-FPC RootDir\>\bin\* дистрибутива стабильной версии компилятора (при помощи которой вы и собираете транк FPC, например, на момент перевода статьи это fpc 3.0.4) в папку *\<Trank-FPC RootDir\>/bin/\$(TargetCPU)-\$(TargetOS)/*, где находится fpc.exe.
3030
3131------------------------------------------------------------------------
3232
3333### Очень короткая инструкция
3434
3535Linux терминал:
3636
3737``` bash
3838 $ cd program_folder
3939 $ gdb program_name
4040 run
4141```
4242
4343Если случилась AV. Пишем:
4444
4545``` bash
4646 bt
4747```
4848
4949### Напрямую из окна стека вызовов
5050
5151Чтобы захватить Backtrace изнутри Lazarus, убедитесь, что вы скомпилировали программу, включающую оба параметра "Generate debug info for GDB" (Генерировать отладочную информацию для GDB) и "Display line numbers in run-time error backtraces (-gl)" (Выдавать номера строк в ошибках времени исполнения (-gl)), и вы правильно настроили GDB в параметрах отладчика.
5252
53531. Запускайте ваше приложение, пока не появится проблема
54542. Если появится диалоговое окно с предупреждением о проблеме, показывающее пару кнопок: "Break" (Прервать) и "Continue" (Продолжить), нажмите кнопку "Break".
55553. Откройте окно Call Stack (Стек вызовов) (Menu View (Вид) -\> Debug Windows (Окна отладки) -\>Call Stack (Стек вызовов)).
56564. Просмотрите список вызовов, при необходимости нажимая "(+)More" (Подробнее)
57575. Нажмите кнопку "Copy All" (Копировать все).
58586. Backtrace теперь в вашем буфере обмена и готов к вставке.
5959
6060### Пользователи Windows
6161
62621\. Откройте окно приглашения MS-DOS
6363
64642\. Перейдите на диск, на котором у вас есть exe:
6565
6666`C: {нажмите enter}`
6767
68683\. Перейдите в каталог, содержащий exe:
6969
7070`cd \myprograms\Project1 {нажмите enter}`
7171
72724\. Загрузите вашу программу с использованием GDB:
7373
7474`gdb Project1.exe {нажмите enter}`
7575
7676### Пользователи Linux/BSD
7777
78781\. Откройте вашу любимую программу Terminal
7979
80802\. Перейдите в каталог, содержащий исполняемый файл:
8181
8282`cd $HOME/myprograms/project1 {нажмите enter}`
8383
84843\. Загрузите вашу программу с использованием GDB:
8585
8686`gdb project1 {нажмите enter}`
8787
8888### macOS
8989
9090GDB по умолчанию недоступен для macOS. Вы можете рассмотреть возможность использования отладчика MacOS по умолчанию [[Creating a Backtrace with lldb|lldb]].
9191
9292#### macOS: Графическое приложение
9393
94941\. Если это еще не сделано: создайте комплект приложений (Project (Проект)/ Project Options (Параметры проекта)/ Application (Приложение)/ Create Application Bundle (Создать комплект приложений))
9595
96962\. Откройте вашу любимую программу терминала
9797
98983\. Перейдите в каталог, содержащий пакет приложения / исполняемый файл:
9999
100100`cd $HOME/myprograms/project1 {нажмите Enter}`
101101
1021024\. Загрузите вашу программу с GDB:
103103
104104`gdb project1.app/Contents/MacOS/project1 {нажмите Enter}`
105105
106106#### macOS: приложение без GUI, консольная программа
107107
1081081\. Откройте вашу любимую программу терминала
109109
1101102\. Перейдите в каталог, содержащий исполняемый файл:
111111
112112`cd $HOME/myprograms/project1 {нажмите Enter}`
113113
1141143\. Загрузите вашу программу с GDB:
115115
116116`gdb project1 {нажмите Enter}`
117117
118118### GDB, готовый принимать команды
119119
120120Теперь вы должны увидеть подсказку, которая выглядит примерно так:
121121
122122`GNU gdb 6.3.50.20050217-cvs`\
123123`Copyright 2004 Free Software Foundation, Inc.`\
124124`GDB is free software, covered by the GNU General Public License, and you are`\
125125`welcome to change it and/or distribute copies of it under certain conditions.`\
126126`Type "show copying" to see the conditions.`\
127127`There is absolutely no warranty for GDB.  Type "show warranty" for details.`\
128128`This GDB was configured as "i686-pc-linux-gnu".`\
129129`(gdb) _`
130130
131131**Пусть GDB остановится при возникновении исключения**
132132
133133`(gdb) break fpc_raiseexception {Нажмите Enter}`
134134
135135**Теперь запустите вашу программу:**
136136
137137`(gdb) run {Нажмите Enter}`
138138
139139Ваша программа будет работать в обычном режиме, пока не произойдет сбой или не произойдет ошибка.
140140
141141Когда ваша программа аварийно завершает работу вместо обычной ошибки «Нарушение прав доступа» или «Деление на ноль», ваша программа просто останавливается, не отвечает и не перерисовывается. Это потому, что GDB поймал ошибку и ждет, когда вы скажете ему, что делать.
142142
143143Переключитесь в окно MS-DOS или Терминал, и у вас должен появиться вывод на экран, похожий на этот:
144144
145145`Program received signal SIGFPE, Arithmetic exception.`\
146146`0x080733aa in TFORM1__BUTTON1CLICK (SENDER=0x403d8bd8, this=0x403d77d8) at unit1.pas:36`\
147147`Current language:  auto; currently pascal`\
148148`(gdb) _`
149149
150150Чтобы создать обратную трассировку, введите:
151151
152152`backtrace {Нажмите Enter}`
153153
154154или
155155
156156`bt {Нажмите Enter}`
157157
158158Теперь у вас должен быть вывод на экран, который выглядит примерно так:
159159
160160`#0  0x080733aa in TFORM1__BUTTON1CLICK (SENDER=0x403d8bd8, this=0x403d77d8) at unit1.pas:36`\
161161`#1  0x080ecd78 in TCONTROL__CLICK (this=0x403d8bd8) at control.inc:1768`\
162162`#2  0x081274bd in TBUTTONCONTROL__CLICK (this=0x403d8bd8) at buttoncontrol.inc:57`\
163163`#3  0x08129171 in TCUSTOMBUTTON__CLICK (this=0x403d8bd8) at buttons.inc:186`\
164164`#4  0x08129198 in TCUSTOMBUTTON__WMDEFAULTCLICKED (MESSAGE={MSG = 1031, WPARAM = `\
165165`        136821192, LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, `\
166166`        WPARAMHI = 2087, LPARAMLO = 59548, LPARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, `\
167167`        this=0x403d8bd8) at buttons.inc:198`\
168168`#5  0x0805bbf7 in SYSTEM_TOBJECT_$__DISPATCH$formal ()`\
169169`#6  0x080ec6e0 in TCONTROL__WNDPROC (THEMESSAGE={MSG = 1031, WPARAM = 136821192, `\
170170`        LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, `\
171171`        LPARAMLO = 59548,  PARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, `\
172172`        this=0x403d8bd8) at control.inc:1447 `\
173173`#7  0x080e4ed9 in TWINCONTROL__WNDPROC (MESSAGE={MSG = 1031, WPARAM = 136821192, `\
174174`        LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, `\
175175`        LPARAMLO = 59548,  PARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, `\
176176`        this=0x403d8bd8) at wincontrol.inc:2154`\
177177`#8  0x08161955 in DELIVERMESSAGE (TARGET=0x403d8bd8, AMESSAGE=void) at gtkproc.inc:3242`\
178178`#9  0x0818897c in GTKWSBUTTON_CLICKED (AWIDGET=0x8285380, AINFO=0x40453794) at gtkwsbuttons.pp:112`\
179179`... { Truncated for simplicity} Complete listing `[[Creating a Backtrace with GDB\Backtrace|here]]\
180180`(gdb) _`
181181
182182> **Note:** Если лог обратной трассировки слишком длинный, вам будет предложено нажать Enter для перехода к следующей странице лога обратной трассировки, пока она не будет завершена.
183183
184184Информация, отображаемая здесь, имеет последовательность событий до того места, где произошла ошибка. См. [[Creating a Backtrace with GDB/ru|Интерпретация результатов Backtrace]]
185185
186186Для выхода из GDB (и вашей программы) вы можете набрать:
187187
188188`quit {Нажмите Enter}`
189189
190190или продолжить работу до следующего типа исключения:
191191
192192`cont {Нажмите Enter}`
193193
194-*Подсказка: в любой момент, когда ваша программа запущена, вы можете нажать <span class="kbd">Ctrl</span> + <span class="kbd">C</span> (из терминала или из командной строки MS-DOS), чтобы получить приглашение "(gdb) _"*
194+*Подсказка: в любой момент, когда ваша программа запущена, вы можете нажать `Ctrl` + `C` (из терминала или из командной строки MS-DOS), чтобы получить приглашение "(gdb) _"*
195195
196196> **Note:** Использование английской раскладки клавиатуры может предотвратить проблемы с GDB (например, если вы вводите специальные символы, такие как ' \\ ').
197197
198198## Использование lldb на Mac
199199
200200Запускаем lldb
201201
202202`lldb`
203203
204204Загружаем ваш проект
205205
206206`target create project1.app/MacOs/Contents/project1`
207207
208-Устанавливаем точку останова</br> Вы можете пропустить это, если проект падает, вместо того, чтобы вызывать исключение fpc. Если есть ожидаемые исключения, которые будут обработаны блоком `try..xcept`, тогда используйте "c" для продолжения
208+Устанавливаем точку останова Вы можете пропустить это, если проект падает, вместо того, чтобы вызывать исключение fpc. Если есть ожидаемые исключения, которые будут обработаны блоком `try..xcept`, тогда используйте "c" для продолжения
209209
210210`breakpoint set --func fpc_raiseexception`
211211
212212Запускаем его
213213
214214`r`
215215
216216Когда он остановится, получаем backtrace
217217
218218`bt`
219219
220220показать локальные снимки для разных кадров (замените 1 в выделенном кадре на другой кадр, например, верхний 3 или верхний 5)
221221
222222`frame select 1`\
223223`frame variable  -P 1`
224224
225225## Получение Backtrace из терминала и на электронную почту
226226
227227В настоящее время мы создали лог обратной трассировки и увидели его в терминале (или в приглашении MS-DOS), но как мне получить его в электронном письме? Есть два способа, о которых я знаю:
228228
2292291. Использовать функцию копирования/вставки вашего терминала (или приглашения MS-DOS)
2302302. Перенаправить вывод GDB в файл следующим образом:
231231
232232`gdb project1 > output.txt`
233233
234234Теперь вы можете открыть файл и скопировать/вставить его в свою электронную почту.
235235
236236Предостережение: второй метод требует, чтобы вы печатали вслепую. Таким образом, вы должны набрать "run", чтобы запустить программу, и "backtrace", чтобы создать обратную трассировку как обычно, но на экране ничего не будет отображаться.
237237
238238Исключение: в Linux вы можете обойтись без возможности увидеть следующую команду:
239239
240240`touch output.txt & tail output.txt -f & gdb project1 > output.txt`
241241
242242## Интерпретация результатов Backtrace
243243
244244Стек содержит все вызовы в тот момент, когда произошла ошибка деления на ноль. В позиции \#0 находится последний вызов "button1-click()". subproc-call \#37 - это первый вызов main () всего приложения.
245245
246246TODO: Напишите мне :)
247247
248248`(gdb) bt`\
249249`#0  0x080733aa in TFORM1__BUTTON1CLICK (SENDER=0x403d8bd8, this=0x403d77d8) at unit1.pas:36`\
250250`#1  0x080ecd78 in TCONTROL__CLICK (this=0x403d8bd8) at control.inc:1768`\
251251`#2  0x081274bd in TBUTTONCONTROL__CLICK (this=0x403d8bd8) at buttoncontrol.inc:57`\
252252`#3  0x08129171 in TCUSTOMBUTTON__CLICK (this=0x403d8bd8) at buttons.inc:186`\
253253`#4  0x08129198 in TCUSTOMBUTTON__WMDEFAULTCLICKED (MESSAGE={MSG = 1031, WPARAM = 136821192, `\
254254`        LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, `\
255255`        LPARAMLO = 59548, LPARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, `\
256256`        this=0x403d8bd8) at buttons.inc:198`\
257257`#5  0x0805bbf7 in SYSTEM_TOBJECT_$__DISPATCH$formal ()`\
258258`#6  0x080ec6e0 in TCONTROL__WNDPROC (THEMESSAGE={MSG = 1031, WPARAM = 136821192, `\
259259`        LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, `\
260260`        LPARAMLO = 59548, LPARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, `\
261261`        this=0x403d8bd8) at control.inc:1447`\
262262`#7  0x080e4ed9 in TWINCONTROL__WNDPROC (MESSAGE={MSG = 1031, WPARAM = 136821192, `\
263263`        LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, `\
264264`        LPARAMLO = 59548, LPARAMHI = 49151, RESULTLO = 27682, RESULTHI =   16416},`\
265265`        this=0x403d8bd8) at wincontrol.inc:2154`\
266266`#8  0x08161955 in DELIVERMESSAGE (TARGET=0x403d8bd8, AMESSAGE=void) at gtkproc.inc:3242`\
267267`#9  0x0818897c in GTKWSBUTTON_CLICKED (AWIDGET=0x8285380, AINFO=0x40453794) at gtkwsbuttons.pp:112`\
268268`#10 0x401d7877 in gtk_marshal_NONE__NONE () from /usr/lib/libgtk-1.2.so.0`\
269269`#11 0x40206e5a in gtk_signal_remove_emission_hook () from /usr/lib/libgtk-1.2.so.0`\
270270`#12 0x4020616a in gtk_signal_set_funcs () from /usr/lib/libgtk-1.2.so.0`\
271271`#13 0x40204234 in gtk_signal_emit () from /usr/lib/libgtk-1.2.so.0`\
272272`#14 0x40176e1c in gtk_button_clicked () from /usr/lib/libgtk-1.2.so.0`\
273273`#15 0x4017838a in gtk_button_get_relief () from /usr/lib/libgtk-1.2.so.0`\
274274`#16 0x401d7877 in gtk_marshal_NONE__NONE () from /usr/lib/libgtk-1.2.so.0`\
275275`#17 0x4020607b in gtk_signal_set_funcs () from /usr/lib/libgtk-1.2.so.0`\
276276`#18 0x40204234 in gtk_signal_emit () from /usr/lib/libgtk-1.2.so.0`\
277277`#19 0x40176d60 in gtk_button_released () from /usr/lib/libgtk-1.2.so.0`\
278278`#20 0x40177d26 in gtk_button_get_relief () from /usr/lib/libgtk-1.2.so.0`\
279279`#21 0x401d764d in gtk_marshal_BOOL__POINTER () from /usr/lib/libgtk-1.2.so.0`\
280280`#22 0x4020619f in gtk_signal_set_funcs () from /usr/lib/libgtk-1.2.so.0`\
281281`#23 0x40204234 in gtk_signal_emit () from /usr/lib/libgtk-1.2.so.0`\
282282`#24 0x40239fd9 in gtk_widget_event () from /usr/lib/libgtk-1.2.so.0`\
283283`#25 0x401d74d0 in gtk_propagate_event () from /usr/lib/libgtk-1.2.so.0`\
284284`#26 0x401d65c1 in gtk_main_do_event () from /usr/lib/libgtk-1.2.so.0`\
285285`#27 0x40065b44 in gdk_wm_protocols_filter () from /usr/lib/libgdk-1.2.so.0`\
286286`#28 0x4003de75 in g_get_current_time () from /usr/lib/libglib-1.2.so.0`\
287287`#29 0x4003e32c in g_get_current_time () from /usr/lib/libglib-1.2.so.0`\
288288`#30 0x4003e4f5 in g_main_iteration () from /usr/lib/libglib-1.2.so.0`\
289289`#31 0x401d6388 in gtk_main_iteration_do () from /usr/lib/libgtk-1.2.so.0`\
290290`#32 0x080b4d26 in TGTKWIDGETSET__WAITMESSAGE (this=0x40473014) at gtkobject.inc:1427`\
291291`#33 0x08070073 in TAPPLICATION__IDLE (this=0x4045b014) at application.inc:319`\
292292`#34 0x08070ffb in TAPPLICATION__HANDLEMESSAGE (this=0x4045b014) at application.inc:827`\
293293`#35 0x08071380 in RUNMESSAGE (parentfp=0xbffff5a4) at application.inc:933`\
294294`#36 0x080712d7 in TAPPLICATION__RUN (this=0x4045b014) at application.inc:944`\
295295`#37 0x080531c3 in main () at project1.lpr:13`\
296296`(gdb)`
297297
298298Этот Backtrace был создан при использовании этого кода:
299299
300300``` pascal
301301 30. procedure TForm1.Button1Click(Sender: TObject);
302302 31. var
303303 32. X, Y, Z: Integer;
304304 33. begin
305305 34. X := 0;
306306 35. Y := 0;
307307 36. Z := X div Y; // ошибка деления на ноль
308308 37. end;
309309```
310310
311311## См. также
312312
313313- [[Creating a Backtrace with lldb]]
314314
315315---
316316*From the Free Pascal wiki, page "Creating a Backtrace with GDB/ru", as it stood on 2019-12-22 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history