Development/Tutorials/Debugging/How to create useful crash reports (ru)
Development/Tutorials/Debugging/How to create useful crash reports
Languages: عربي | Asturianu | Català | Česky | Kaszëbsczi | Dansk | Deutsch | English | Esperanto | Español | Eesti | فارسی | Suomi | Français | Galego | Italiano | 日本語 | 한국어 | Norwegian | Polski | Português Brasileiro | Română | Русский | Svenska | Slovenčina | Slovenščina | српски | Türkçe | Tiếng Việt | Українська | 简体中文 | 繁體中文
Введение
В этой статье описано, как создать полезный отчет с трассировкой упавшего приложения KDE. Сначала приведем общую информацию. Затем мы опишем несколько способов трассировки с помощью полезных отладчиков GNU Debugger и Valgrind.
Как создать полезный crash report (отчет об упавшем приложении)
Хороший отчет об упавшем приложении в Bugzilla состоит из двух частей: описание того, как воспроизвести краш приложения и трассировка этого краша. Если один из этих элементов отсутствует, то разработчикам гораздо сложнее решить проблему.
Описание должно состоять больше, чем из просто "оно рухнуло". Попытайтесь описать все, что Вы делали до того, как приложение упало. Нажали ли Вы на кнопку, открыли ли какой-то вебсайт или файл, что привело к проблеме? Эти мелкие детали могут выглядеть бесполезными для Вас, но быть полезными для разработчиков, поэтому просто опишите их.
Более серьезные статьи по тому, как писать хорошие описания ошибок, доступны по этой ссылке. Пожалуйста, прочитайте их до того, как посылать отчеты об ошибках.
Не прикладывайте трассировку к отчету об ошибке. Вместо этого просто вставьте ее. Это лучше, поскольку у разработчиков появляется возможность поиска отчетов-дубликатов. (Приложенные файлы с трассировками не будут найдены.)
Если Вы вставите трассировку в отчет, убедитесь, что Вы вырезали все, кроме одной-двух,
(no debugging symbols found)
строки из трассировки, так как они затрудняют чтение.
Хотя вставка трассировки напрямую предпочтительнее, чем прикрепление файла, пожалуйста, не вставляйте в отчет логи (valgrind, strace или вывод терминала) или примеры данных (почта, HTML файлы и т.д.). Прикрепляйте такие вещи как файлы.
Трассировка
Трассировка необходима. Она может выглядеть бессмысленной для Вас, но она может содержать много полезной информации. Трассировка описывает, какие функции были вызваны до краша, так что разработчики могут выяснить, в какой из них началась неразбериха. Хорошая трассировка имеет и обратную сторону: библиотеки и исполняемые файлы занимают больше дискового пространства, чем их оптимизированные "братья". Поэтому во многих дистрибутивах установлены укороченные (обрезанные) файлы, которые приводят к бесполезным трассировкам:
(no debugging symbols found) Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1". (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) [Thread debugging using libthread_db enabled] [New Thread -1233848624 (LWP 12212)] [New Thread -1255081072 (LWP 12820)] [New Thread -1240921200 (LWP 12819)] [New Thread -1266680944 (LWP 12818)] (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) 0xffffe410 in __kernel_vsyscall () #0 0xffffe410 in __kernel_vsyscall () #1 0xb6a1210b in ?? () from /lib/tls/i686/cmov/libpthread.so.0 #2 0xb6a85afe in ?? () from /usr/lib/libX11.so.6 #3 0x00000003 in ?? () #4 0x082149c0 in ?? () #5 0x00003ffc in ?? () #6 0x00000000 in ?? ()
Но не волнуйтесь, с помощью некоторых модификаций Вы можете создать полный вывод трассировки для приложений KDE.
Подготовка пакетов KDE
Если Ваш дистрибутив имеет пакеты для отладки, то установите их.
Взглянув на трассировочный вывод, легко увидеть, каких пакетов отладки Вам не хватает. Например, рассмотрим следующую строку из трассировки:
#6 0xb7975bdc in ?? () from /usr/lib/libkmailprivate.so.4
?? обозначают, что библиотека libkmailprivate.so.4 не имеет отладочной информации, которая могла бы быть доступна в отдельном пакете для отладки. В этом случае, легко решить, что Вам необходимо установить пакет для отладки KMail, чтобы получить лучший вывод трассировки.
Иногда Вам необходимо установить более, чем один, пакет для отладки, чтобы получить хорошую трассировку. Это зависит от Вашего дистрибутива. Например, в некоторых дистрибутивах достаточно установить пакет отладки для kdepim, чтобы получить достаточную отладочную информацию для крашей в KMail, в других дистрибутивах необходим дополнительный отладочный пакет именно для KMail.
Далее приводится список, из которого можно узнать, как получить пакеты отладки для некоторых дистрибутивов:
- Debian - Debian предлагает -dbg пакеты для легкого создания полезных трассировок. Просто установите требующиеся -dbg пакеты. Например, kdepim-dbg для крашей KMail. Зависимости -dbg нужны для того, чтобы быть уверенными в наличии соответствующих пакетов (kdelibs-dbg, gdb, и т.д.).
- FreeBSD ports - Пожалуйста, последуйте по ссылке KDE на FreeBSD FAQ.
- Gentoo - Gentoo имеет свой собственный документ, описывающий данную проблему.
- Mandriva - Mandriva 2007.0 и выше имеет дополнительные отладочные пакеты для всего KDE (фактически для всех его пакетов). Просто установите соответствующие -debug пакеты такие, как kdebase-debug и kdemultimedia-debug. Вы вероятно захотите установить kdelibs-debug в любом случае.
- Примечание: -debug пакеты находятся в отдельных репозиториях. Например, для всех пакетов в main, Вы найдете отладочные пакеты в репозитории debug_main.
- Kubuntu/Ubuntu - Семейство Ubuntu дистрибутивов делает вещи довольно простыми. Каждый официальный модуль KDE имеет в репозитории отдельный пакет с суффиксом -dbg. Всегда устанавливайте kdelibs5-dbg, потому что все приложения KDE используют kdelibs (kdelibs-dbg для приложений KDE 3). Затем Вам следует установить -dbg пакет для упавшего приложения. Например, если упал KOrganizer, Вам следует, конечно же, установить kdepim-dbg. Если программа не из официального модуля KDE и не имеет -dbg пакета, то Вы можете установить -dbgsym пакетиз репозиториев, приведенных на этой Debugging Program Crashes странице.
- openSUSE - Вам следует установить -debuginfo пакеты, например: kdepimlibs4-debuginfo. Вы можете найти эти пакеты в KDE репозиториях. Также есть отдельная страница, посвященная отладке в openSUSE.
- Fedora - Fedora имеет свой собственный документ, описывающий данную проблему. (debuginfo репозиторий должен быть разрешенным.)
Если Ваш дистрибутив не имеет отладочных пакетов для KDE, Вам следует скомпилировать KDE из исходников:
- Если Вы используете KDE 3, тогда на стадии конфигурации следует использовать параметр --enable-debug=full, чтобы собрать отладочные символы.
- Если Вы используете KDE 4, то на стадии cmake следует использовать параметр -DCMAKE_BUILD_TYPE=debugfull. Если Вы желаете определить свой собственный CXXFLAGS, то используйте -DCMAKE_BUILD_TYPE=None CMAKE_CXX_FLAGS="-O0 -g". Вы можете можете изменить CMAKE_CXX_FLAGS так, как Вам нужно.
Затем просто вызываете make и make install, как Вы всегда делаете.
Crash!
Итак, время "уронить" Ваше приложение. The KDE Crash Dialog should appear right after the crash, which shows the Backtrace tab.
Click that tab and wait for a minute. This process may take quite some memory, so things may go sluggish all of a sudden. But the result should look much better. For example:
Using host libthread_db library "/lib/libthread_db.so.1". [Thread debugging using libthread_db enabled] [New Thread -1232783168 (LWP 7604)] [KCrash handler]
- 6 0x0806be76 in TreeMapItem::parent (this=0x0)
at /home/bram/KDE/kde3/kdeaddons/konq-plugins/fsview/treemap.h:285
- 7 0x08065fea in TreeMapItemList::compareItems (this=0xbfec04a8, item1=0x0,
item2=0x0) at /home/bram/KDE/kde3/kdeaddons/konq-plugins/fsview/treemap.cpp:720
- 8 0xb7281619 in QGList::operator== () from /usr/qt/3/lib/libqt-mt.so.3
- 9 0x0806d498 in QPtrList<TreeMapItem>::operator== (this=0xbfec04a8,
list=@0xbfec0468) at /usr/qt/3/include/qptrlist.h:74
- 10 0x08062e18 in TreeMapWidget::mousePressEvent (this=0xbfec03ac,
e=0xbfebff1c) at /home/bram/KDE/kde3/kdeaddons/konq-plugins/fsview/treemap.cpp:1840
- 11 0xb7004a63 in QWidget::event () from /usr/qt/3/lib/libqt-mt.so.3
- 12 0xb6f6bca7 in QApplication::internalNotify ()
from /usr/qt/3/lib/libqt-mt.so.3
- 13 0xb6f6ca88 in QApplication::notify () from /usr/qt/3/lib/libqt-mt.so.3
- 14 0xb7725a84 in KApplication::notify (this=0xbfec055c, receiver=0xbfec03ac,
event=0xbfebff1c) at /home/bram/KDE/kde3/kdelibs/kdecore/kapplication.cpp:550
- 15 0xb6f0bfd2 in QETWidget::translateMouseEvent ()
from /usr/qt/3/lib/libqt-mt.so.3
- 16 0xb6f0b8b0 in QApplication::x11ProcessEvent ()
from /usr/qt/3/lib/libqt-mt.so.3
- 17 0xb6f1b761 in QEventLoop::processEvents () from /usr/qt/3/lib/libqt-mt.so.3
- 18 0xb6f82831 in QEventLoop::enterLoop () from /usr/qt/3/lib/libqt-mt.so.3
- 19 0xb6f826b6 in QEventLoop::exec () from /usr/qt/3/lib/libqt-mt.so.3
- 20 0xb6f6b72f in QApplication::exec () from /usr/qt/3/lib/libqt-mt.so.3
- 21 0x0805181e in main (argc=134673960, argv=0xffffffff)
at /home/bram/KDE/kde3/kdeaddons/konq-plugins/fsview/main.cpp:55
This looks better, right? It shows memory addresses, the source files and line numbers and the parameters passed to functions. Which make it more helpful to the developer where to look for the problem.
Note noframe You need GDB installed to get the backtrace of a crash. Please read the next section to know what GDB is, and how to install it.
Retrieving a backtrace with GDB
In some cases, it is not possible to create a backtrace with the KDE Crash Dialog. This may be caused by an application which entered an infinite loop, or the crash dialog did not appear at all for some reason. You can try to grab a backtrace with gdb, the GNU Debugger. GDB is widely available through distribution packages.
Invoking GDB differs from the situation. You can run an application from inside gdb, or attach gdb to an already running process. The latter may be useful when an application already has entered an infinite loop. But we will first start with running an application inside gdb. From the shell, run:
$ gdb someKDEapp
The GDB prompt will appear. Note that this does not start the application itself, you should run it by invoking the run command:
(gdb) run
This will run the application like you are used to, and you can work with it like normal (it only consumes far more memory and may feel sluggish). Now it's time to reproduce your crash. When you succeed, the application just closes and you should return to your GDB prompt. Now it's time to run the 'backtrace' command:
Note noframe Some KDE applications (such as JuK and KTorrent) have special code to ensure that there is only one running instance of the application at a time. For these applications you should type in "run --nofork" at the (gdb) prompt instead of "run" because otherwise gdb will try to debug the wrong process. If you are unsure as to whether to use --nofork just try it. If the application says it's an unknown option you can remove --nofork.
(gdb) thread apply all backtrace
This should give a good backtrace which can be posted at the KDE Bugzilla.
In case you want to attach to an existing process, run the following command in the shell:
$ gdb someKDEapp pid
where pid is the process ID of the process you want to attach to. Once attached, and the process is in an infinite loop, after using the 'backtrace' command again a useful backtrace will appear. You can use 'continue' command to let the application run again and press Ctrl+C in gdb to be able to again enter commands.
Получение трассировки с помощью Valgrind
When it comes to crashes, Valgrind is also a useful tool to create a backtrace. It's not a substitution for GDB, but rather a supplement.
When you run an application in valgrind, every piece of memory read or written by the application is being checked. Valgrind will report erroneous memory operations in the standard output or in a log file. Since most crashes are due to an invalid memory read, valgrind can be useful to track down where the problem occurs.
Note noframe Valgrind consists of several tools in order to check or profile an application. For this article, we only use memcheck, the default tool when valgrind is being invoked.
Like GDB, Valgrind makes running an application much slower, while consuming a lot more resources.
Start the application within valgrind:
$ valgrind --log-file=someKDEapp someKDEapp
Now reproduce the crash. As soon as this happens, the application and valgrind will terminate. What's left is a file named someKDEapp.pid where pid is replaced by the process ID of the valgrind process. The file may list more errors than the one causing the crash. Here's the bit causing the crash which corresponds to the GDB backtrace above:
==23292== Invalid read of size 4 ==23292== at 0x806BD9E: TreeMapItem::parent() const (treemap.h:285) ==23292== by 0x8065FB9: TreeMapItemList::compareItems(void*, void*) (treemap.cpp:720) ==23292== by 0x50AC618: QGList::operator==(QGList const&) const (in /usr/qt/3/lib/libqt-mt.so.3.3.8) ==23292== by 0x806D3BF: QPtrList<TreeMapItem>::operator==(QPtrList<TreeMapItem> const&) const (qptrlist.h:74) ==23292== by 0x8062DE7: TreeMapWidget::mousePressEvent(QMouseEvent*) (treemap.cpp:1840) ==23292== by 0x4E2FA62: QWidget::event(QEvent*) (in /usr/qt/3/lib/libqt-mt.so.3.3.8) ==23292== by 0x4D96CA6: QApplication::internalNotify(QObject*, QEvent*) (in /usr/qt/3/lib/libqt-mt.so.3.3.8) ==23292== by 0x4D97A87: QApplication::notify(QObject*, QEvent*) (in /usr/qt/3/lib/libqt-mt.so.3.3.8) ==23292== by 0x4809AC3: KApplication::notify(QObject*, QEvent*) (kapplication.cpp:550) ==23292== by 0x4D36FD1: QETWidget::translateMouseEvent(_XEvent const*) (in /usr/qt/3/lib/libqt-mt.so.3.3.8) ==23292== by 0x4D368AF: QApplication::x11ProcessEvent(_XEvent*) (in /usr/qt/3/lib/libqt-mt.so.3.3.8) ==23292== by 0x4D46760: QEventLoop::processEvents(unsigned) (in /usr/qt/3/lib/libqt-mt.so.3.3.8) ==23292== Address 0x2C is not stack'd, malloc'd or (recently) free'd
But to be sure, just attach the whole log file to the crash report.