Sign in Join
Wiki copytemporary

Creating a Backtrace with GDB/ru: what changed

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

Title: Creating a Backtrace with GDB/ru

OldNewLine
1+## Причины для создания обратной трассировки
2+
3+### Отчеты об ошибках
4+
5+Файлы обратной трассировки могут быть очень полезны при отправке отчетов об ошибках. Они, несомненно, повысят вероятность того, что ошибка будет исправлена раньше.
6+
7+### Помоги себе найти проблему
8+
9+Обратная трассировка может действительно облегчить поиск проблемы с вашей собственной программой. Часто проблема выявляется сразу.
10+
11+### Это просто весело!!!
12+
13+Хорошо, это может быть преувеличением, но делать обратную трассировку просто весело!
14+
15+Если серьезно, если вы можете придумать другую причину создания обратной трассировки, добавьте ее сюда.
16+
17+## Создание Backtrace
18+
19+> **Note:** **Mac-пользователям** следует использовать *lldb* вместо *gdb*.
20+
21+Чтобы создать обратную трассировку с помощью [[GDB]] (Gnu DeBugger):
22+
23+1. У вас должна быть программа [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.
24+2. GDB должен быть прописан в переменной окружения PATH. Если это Windows, из командной строки введите (пример): установите PATH =% PATH%; set PATH=%PATH%;c:\lazarus\mingw\bin\\
25+3. Программа, которую вы хотите отладить, ДОЛЖНА иметь отладочную информацию, включенную в исполняемый файл. Если вы используете "strip", "upx", компилируете с "Xs" или использовали какой-либо другой exe-упаковщик, это не сработает!
26+
27+------------------------------------------------------------------------
28+
29+Прим.перев.: если вы используете транковые svn-сборки FPC для Windows, то после компиляции gdb.exe в них отсутствует.Его необходимо скопировать (вместе с некоторыми другими утилитами) из папки *\<Stable-FPC RootDir\>\bin\* дистрибутива стабильной версии компилятора (при помощи которой вы и собираете транк FPC, например, на момент перевода статьи это fpc 3.0.4) в папку *\<Trank-FPC RootDir\>/bin/\$(TargetCPU)-\$(TargetOS)/*, где находится fpc.exe.
30+
31+------------------------------------------------------------------------
32+
33+### Очень короткая инструкция
34+
35+Linux терминал:
36+
37+``` bash
38+ $ cd program_folder
39+ $ gdb program_name
40+ run
41+```
42+
43+Если случилась AV. Пишем:
44+
45+``` bash
46+ bt
47+```
48+
49+### Напрямую из окна стека вызовов
50+
51+Чтобы захватить Backtrace изнутри Lazarus, убедитесь, что вы скомпилировали программу, включающую оба параметра "Generate debug info for GDB" (Генерировать отладочную информацию для GDB) и "Display line numbers in run-time error backtraces (-gl)" (Выдавать номера строк в ошибках времени исполнения (-gl)), и вы правильно настроили GDB в параметрах отладчика.
52+
53+1. Запускайте ваше приложение, пока не появится проблема
54+2. Если появится диалоговое окно с предупреждением о проблеме, показывающее пару кнопок: "Break" (Прервать) и "Continue" (Продолжить), нажмите кнопку "Break".
55+3. Откройте окно Call Stack (Стек вызовов) (Menu View (Вид) -\> Debug Windows (Окна отладки) -\>Call Stack (Стек вызовов)).
56+4. Просмотрите список вызовов, при необходимости нажимая "(+)More" (Подробнее)
57+5. Нажмите кнопку "Copy All" (Копировать все).
58+6. Backtrace теперь в вашем буфере обмена и готов к вставке.
59+
60+### Пользователи Windows
61+
62+1\. Откройте окно приглашения MS-DOS
63+
64+2\. Перейдите на диск, на котором у вас есть exe:
65+
66+`C: {нажмите enter}`
67+
68+3\. Перейдите в каталог, содержащий exe:
69+
70+`cd \myprograms\Project1 {нажмите enter}`
71+
72+4\. Загрузите вашу программу с использованием GDB:
73+
74+`gdb Project1.exe {нажмите enter}`
75+
76+### Пользователи Linux/BSD
77+
78+1\. Откройте вашу любимую программу Terminal
79+
80+2\. Перейдите в каталог, содержащий исполняемый файл:
81+
82+`cd $HOME/myprograms/project1 {нажмите enter}`
83+
84+3\. Загрузите вашу программу с использованием GDB:
85+
86+`gdb project1 {нажмите enter}`
87+
88+### macOS
89+
90+GDB по умолчанию недоступен для macOS. Вы можете рассмотреть возможность использования отладчика MacOS по умолчанию [[Creating a Backtrace with lldb|lldb]].
91+
92+#### macOS: Графическое приложение
93+
94+1\. Если это еще не сделано: создайте комплект приложений (Project (Проект)/ Project Options (Параметры проекта)/ Application (Приложение)/ Create Application Bundle (Создать комплект приложений))
95+
96+2\. Откройте вашу любимую программу терминала
97+
98+3\. Перейдите в каталог, содержащий пакет приложения / исполняемый файл:
99+
100+`cd $HOME/myprograms/project1 {нажмите Enter}`
101+
102+4\. Загрузите вашу программу с GDB:
103+
104+`gdb project1.app/Contents/MacOS/project1 {нажмите Enter}`
105+
106+#### macOS: приложение без GUI, консольная программа
107+
108+1\. Откройте вашу любимую программу терминала
109+
110+2\. Перейдите в каталог, содержащий исполняемый файл:
111+
112+`cd $HOME/myprograms/project1 {нажмите Enter}`
113+
114+3\. Загрузите вашу программу с GDB:
115+
116+`gdb project1 {нажмите Enter}`
117+
118+### GDB, готовый принимать команды
119+
120+Теперь вы должны увидеть подсказку, которая выглядит примерно так:
121+
122+`GNU gdb 6.3.50.20050217-cvs`\
123+`Copyright 2004 Free Software Foundation, Inc.`\
124+`GDB is free software, covered by the GNU General Public License, and you are`\
125+`welcome to change it and/or distribute copies of it under certain conditions.`\
126+`Type "show copying" to see the conditions.`\
127+`There is absolutely no warranty for GDB.  Type "show warranty" for details.`\
128+`This GDB was configured as "i686-pc-linux-gnu".`\
129+`(gdb) _`
130+
131+**Пусть GDB остановится при возникновении исключения**
132+
133+`(gdb) break fpc_raiseexception {Нажмите Enter}`
134+
135+**Теперь запустите вашу программу:**
136+
137+`(gdb) run {Нажмите Enter}`
138+
139+Ваша программа будет работать в обычном режиме, пока не произойдет сбой или не произойдет ошибка.
140+
141+Когда ваша программа аварийно завершает работу вместо обычной ошибки «Нарушение прав доступа» или «Деление на ноль», ваша программа просто останавливается, не отвечает и не перерисовывается. Это потому, что GDB поймал ошибку и ждет, когда вы скажете ему, что делать.
142+
143+Переключитесь в окно MS-DOS или Терминал, и у вас должен появиться вывод на экран, похожий на этот:
144+
145+`Program received signal SIGFPE, Arithmetic exception.`\
146+`0x080733aa in TFORM1__BUTTON1CLICK (SENDER=0x403d8bd8, this=0x403d77d8) at unit1.pas:36`\
147+`Current language:  auto; currently pascal`\
148+`(gdb) _`
149+
150+Чтобы создать обратную трассировку, введите:
151+
152+`backtrace {Нажмите Enter}`
153+
154+или
155+
156+`bt {Нажмите Enter}`
157+
158+Теперь у вас должен быть вывод на экран, который выглядит примерно так:
159+
160+`#0  0x080733aa in TFORM1__BUTTON1CLICK (SENDER=0x403d8bd8, this=0x403d77d8) at unit1.pas:36`\
161+`#1  0x080ecd78 in TCONTROL__CLICK (this=0x403d8bd8) at control.inc:1768`\
162+`#2  0x081274bd in TBUTTONCONTROL__CLICK (this=0x403d8bd8) at buttoncontrol.inc:57`\
163+`#3  0x08129171 in TCUSTOMBUTTON__CLICK (this=0x403d8bd8) at buttons.inc:186`\
164+`#4  0x08129198 in TCUSTOMBUTTON__WMDEFAULTCLICKED (MESSAGE={MSG = 1031, WPARAM = `\
165+`        136821192, LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, `\
166+`        WPARAMHI = 2087, LPARAMLO = 59548, LPARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, `\
167+`        this=0x403d8bd8) at buttons.inc:198`\
168+`#5  0x0805bbf7 in SYSTEM_TOBJECT_$__DISPATCH$formal ()`\
169+`#6  0x080ec6e0 in TCONTROL__WNDPROC (THEMESSAGE={MSG = 1031, WPARAM = 136821192, `\
170+`        LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, `\
171+`        LPARAMLO = 59548,  PARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, `\
172+`        this=0x403d8bd8) at control.inc:1447 `\
173+`#7  0x080e4ed9 in TWINCONTROL__WNDPROC (MESSAGE={MSG = 1031, WPARAM = 136821192, `\
174+`        LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, `\
175+`        LPARAMLO = 59548,  PARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, `\
176+`        this=0x403d8bd8) at wincontrol.inc:2154`\
177+`#8  0x08161955 in DELIVERMESSAGE (TARGET=0x403d8bd8, AMESSAGE=void) at gtkproc.inc:3242`\
178+`#9  0x0818897c in GTKWSBUTTON_CLICKED (AWIDGET=0x8285380, AINFO=0x40453794) at gtkwsbuttons.pp:112`\
179+`... { Truncated for simplicity} Complete listing `[[Creating a Backtrace with GDB\Backtrace|here]]\
180+`(gdb) _`
181+
182+> **Note:** Если лог обратной трассировки слишком длинный, вам будет предложено нажать Enter для перехода к следующей странице лога обратной трассировки, пока она не будет завершена.
183+
184+Информация, отображаемая здесь, имеет последовательность событий до того места, где произошла ошибка. См. [[Creating a Backtrace with GDB/ru|Интерпретация результатов Backtrace]]
185+
186+Для выхода из GDB (и вашей программы) вы можете набрать:
187+
188+`quit {Нажмите Enter}`
189+
190+или продолжить работу до следующего типа исключения:
191+
192+`cont {Нажмите Enter}`
193+
194+*Подсказка: в любой момент, когда ваша программа запущена, вы можете нажать <span class="kbd">Ctrl</span> + <span class="kbd">C</span> (из терминала или из командной строки MS-DOS), чтобы получить приглашение "(gdb) _"*
195+
196+> **Note:** Использование английской раскладки клавиатуры может предотвратить проблемы с GDB (например, если вы вводите специальные символы, такие как ' \\ ').
197+
198+## Использование lldb на Mac
199+
200+Запускаем lldb
201+
202+`lldb`
203+
204+Загружаем ваш проект
205+
206+`target create project1.app/MacOs/Contents/project1`
207+
208+Устанавливаем точку останова</br> Вы можете пропустить это, если проект падает, вместо того, чтобы вызывать исключение fpc. Если есть ожидаемые исключения, которые будут обработаны блоком `try..xcept`, тогда используйте "c" для продолжения
209+
210+`breakpoint set --func fpc_raiseexception`
211+
212+Запускаем его
213+
214+`r`
215+
216+Когда он остановится, получаем backtrace
217+
218+`bt`
219+
220+показать локальные снимки для разных кадров (замените 1 в выделенном кадре на другой кадр, например, верхний 3 или верхний 5)
221+
222+`frame select 1`\
223+`frame variable  -P 1`
224+
225+## Получение Backtrace из терминала и на электронную почту
226+
227+В настоящее время мы создали лог обратной трассировки и увидели его в терминале (или в приглашении MS-DOS), но как мне получить его в электронном письме? Есть два способа, о которых я знаю:
228+
229+1. Использовать функцию копирования/вставки вашего терминала (или приглашения MS-DOS)
230+2. Перенаправить вывод GDB в файл следующим образом:
231+
232+`gdb project1 > output.txt`
233+
234+Теперь вы можете открыть файл и скопировать/вставить его в свою электронную почту.
235+
236+Предостережение: второй метод требует, чтобы вы печатали вслепую. Таким образом, вы должны набрать "run", чтобы запустить программу, и "backtrace", чтобы создать обратную трассировку как обычно, но на экране ничего не будет отображаться.
237+
238+Исключение: в Linux вы можете обойтись без возможности увидеть следующую команду:
239+
240+`touch output.txt & tail output.txt -f & gdb project1 > output.txt`
241+
242+## Интерпретация результатов Backtrace
243+
244+Стек содержит все вызовы в тот момент, когда произошла ошибка деления на ноль. В позиции \#0 находится последний вызов "button1-click()". subproc-call \#37 - это первый вызов main () всего приложения.
245+
246+TODO: Напишите мне :)
247+
248+`(gdb) bt`\
249+`#0  0x080733aa in TFORM1__BUTTON1CLICK (SENDER=0x403d8bd8, this=0x403d77d8) at unit1.pas:36`\
250+`#1  0x080ecd78 in TCONTROL__CLICK (this=0x403d8bd8) at control.inc:1768`\
251+`#2  0x081274bd in TBUTTONCONTROL__CLICK (this=0x403d8bd8) at buttoncontrol.inc:57`\
252+`#3  0x08129171 in TCUSTOMBUTTON__CLICK (this=0x403d8bd8) at buttons.inc:186`\
253+`#4  0x08129198 in TCUSTOMBUTTON__WMDEFAULTCLICKED (MESSAGE={MSG = 1031, WPARAM = 136821192, `\
254+`        LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, `\
255+`        LPARAMLO = 59548, LPARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, `\
256+`        this=0x403d8bd8) at buttons.inc:198`\
257+`#5  0x0805bbf7 in SYSTEM_TOBJECT_$__DISPATCH$formal ()`\
258+`#6  0x080ec6e0 in TCONTROL__WNDPROC (THEMESSAGE={MSG = 1031, WPARAM = 136821192, `\
259+`        LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, `\
260+`        LPARAMLO = 59548, LPARAMHI = 49151, RESULTLO = 27682, RESULTHI = 16416}, `\
261+`        this=0x403d8bd8) at control.inc:1447`\
262+`#7  0x080e4ed9 in TWINCONTROL__WNDPROC (MESSAGE={MSG = 1031, WPARAM = 136821192, `\
263+`        LPARAM = -1073747812, RESULT = 1075866658, WPARAMLO = 47560, WPARAMHI = 2087, `\
264+`        LPARAMLO = 59548, LPARAMHI = 49151, RESULTLO = 27682, RESULTHI =   16416},`\
265+`        this=0x403d8bd8) at wincontrol.inc:2154`\
266+`#8  0x08161955 in DELIVERMESSAGE (TARGET=0x403d8bd8, AMESSAGE=void) at gtkproc.inc:3242`\
267+`#9  0x0818897c in GTKWSBUTTON_CLICKED (AWIDGET=0x8285380, AINFO=0x40453794) at gtkwsbuttons.pp:112`\
268+`#10 0x401d7877 in gtk_marshal_NONE__NONE () from /usr/lib/libgtk-1.2.so.0`\
269+`#11 0x40206e5a in gtk_signal_remove_emission_hook () from /usr/lib/libgtk-1.2.so.0`\
270+`#12 0x4020616a in gtk_signal_set_funcs () from /usr/lib/libgtk-1.2.so.0`\
271+`#13 0x40204234 in gtk_signal_emit () from /usr/lib/libgtk-1.2.so.0`\
272+`#14 0x40176e1c in gtk_button_clicked () from /usr/lib/libgtk-1.2.so.0`\
273+`#15 0x4017838a in gtk_button_get_relief () from /usr/lib/libgtk-1.2.so.0`\
274+`#16 0x401d7877 in gtk_marshal_NONE__NONE () from /usr/lib/libgtk-1.2.so.0`\
275+`#17 0x4020607b in gtk_signal_set_funcs () from /usr/lib/libgtk-1.2.so.0`\
276+`#18 0x40204234 in gtk_signal_emit () from /usr/lib/libgtk-1.2.so.0`\
277+`#19 0x40176d60 in gtk_button_released () from /usr/lib/libgtk-1.2.so.0`\
278+`#20 0x40177d26 in gtk_button_get_relief () from /usr/lib/libgtk-1.2.so.0`\
279+`#21 0x401d764d in gtk_marshal_BOOL__POINTER () from /usr/lib/libgtk-1.2.so.0`\
280+`#22 0x4020619f in gtk_signal_set_funcs () from /usr/lib/libgtk-1.2.so.0`\
281+`#23 0x40204234 in gtk_signal_emit () from /usr/lib/libgtk-1.2.so.0`\
282+`#24 0x40239fd9 in gtk_widget_event () from /usr/lib/libgtk-1.2.so.0`\
283+`#25 0x401d74d0 in gtk_propagate_event () from /usr/lib/libgtk-1.2.so.0`\
284+`#26 0x401d65c1 in gtk_main_do_event () from /usr/lib/libgtk-1.2.so.0`\
285+`#27 0x40065b44 in gdk_wm_protocols_filter () from /usr/lib/libgdk-1.2.so.0`\
286+`#28 0x4003de75 in g_get_current_time () from /usr/lib/libglib-1.2.so.0`\
287+`#29 0x4003e32c in g_get_current_time () from /usr/lib/libglib-1.2.so.0`\
288+`#30 0x4003e4f5 in g_main_iteration () from /usr/lib/libglib-1.2.so.0`\
289+`#31 0x401d6388 in gtk_main_iteration_do () from /usr/lib/libgtk-1.2.so.0`\
290+`#32 0x080b4d26 in TGTKWIDGETSET__WAITMESSAGE (this=0x40473014) at gtkobject.inc:1427`\
291+`#33 0x08070073 in TAPPLICATION__IDLE (this=0x4045b014) at application.inc:319`\
292+`#34 0x08070ffb in TAPPLICATION__HANDLEMESSAGE (this=0x4045b014) at application.inc:827`\
293+`#35 0x08071380 in RUNMESSAGE (parentfp=0xbffff5a4) at application.inc:933`\
294+`#36 0x080712d7 in TAPPLICATION__RUN (this=0x4045b014) at application.inc:944`\
295+`#37 0x080531c3 in main () at project1.lpr:13`\
296+`(gdb)`
297+
298+Этот Backtrace был создан при использовании этого кода:
299+
300+``` pascal
301+ 30. procedure TForm1.Button1Click(Sender: TObject);
302+ 31. var
303+ 32. X, Y, Z: Integer;
304+ 33. begin
305+ 34. X := 0;
306+ 35. Y := 0;
307+ 36. Z := X div Y; // ошибка деления на ноль
308+ 37. end;
309+```
310+
311+## См. также
312+
313+- [[Creating a Backtrace with lldb]]
314+
315+---
316+*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