Каков хороший способ создать строку для отчетов о сбоях Win32 C ++, которая отражает причину сбоя? - PullRequest
1 голос
/ 06 января 2011

Мы используем Fogbugz для отслеживания проблем, и я нахожусь в процессе написания оболочки C ++ для XML API для Fogbugz .

Лучше всего использовать поле " scout ", чтобы подобные / одинаковые сбои просто учитывались, но не сообщались снова.Для этого нам нужна уникальная строка для конкретной причины сбоя.

В Win32 - после получения файла dmp или другого обработчика сбоя, что является хорошим способом сделать уникальную строку для сбоя?(мы собираемся создать файл dmp и отправить его на сервер fogbugz)

В предыдущих публикациях / статьях / и т. д. Джоэл делал различные предложения, но большинство из них рассчитывали на язык, такой как C #, который использует отражение иу вас есть много информации, которую трудно или невозможно получить.

Есть ли у других людей такие вещи, как следы стека или другие вещи, чтобы делать записи разведчика в fogbugz?

РЕДАКТИРОВАТЬ Вуточнить - нам не нужен уникальный идентификатор для каждого инцидента - есть вероятность сбоев с одинаковым путем кода.Мы хотим запечатлеть это.Я думал, что мы получим последние несколько вызовов стека, которые есть в нашем коде (а не из библиотек win32), но не уверен, как это сделать.

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

EDIT

Я думаю, что нам нужна общая "сигнатура" сбоя - в зависимости от того, что находится в стеке.Подобные стеки должны иметь одинаковую подпись.Например - возьмите 5 лучших методов, которые есть в нашем приложении, а затем первый вызов (если есть), который мы делаем в MS DLL.Этого, вероятно, будет достаточно для подписи и, скорее всего, будет коррелировать сбои, которые являются «одинаковыми».

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

РЕДАКТИРОВАТЬ - ПРИМЕЧАНИЕ. Мы хотим создать "идентификатор корзины" / подпись в обработчике исключений, чтобы мы могли создать мини-дамп иотправьте его в fogbugz в качестве описания разведчика.В качестве альтернативы мы можем загрузить дамп при следующем запуске приложения и затем отправить его с подписью, которую мы сгенерируем.

Ответы [ 6 ]

1 голос
/ 24 ноября 2017

Возможно, уже немного поздно, но я также добавлю свое решение на случай, если оно может помочь другим людям. Вы можете сделать это, используя дураков из «Средства отладки для Windows», например windbg.exe или лучше kd.exe. Запустив команду "kd.exe -z" path_to_dump.dmp "-c" kd; q ">> dumpstack.txt, вы можете получить следующий результат:

Microsoft (R) Windows Debugger Версия 10.0.15063.400 X86 Авторские права (c) Корпорация Microsoft. Все права защищены.

Загрузка файла дампа [d: \ work \ bugs \ 14122 \ myexe.exe.2624.dmp] Пользовательский мини-файл дампа с полной памятью: доступны только данные приложения

************* Symbol Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       srv*C:\Symbols*http://msdl.microsoft.com/download/symbols
Symbol search path is: srv*C:\Symbols*http://msdl.microsoft.com/download/symbols
Executable search path is: 
Windows 10 Version 15063 MP (4 procs) Free x86 compatible
Product: WinNt, suite: SingleUserTS
15063.0.x86fre.rs2_release.170317-1834
Machine Name:
Debug session time: Fri Oct 13 00:09:01.000 2017 (UTC + 1:00)
System Uptime: 0 days 0:18:33.797
Process Uptime: 0 days 0:03:40.000
................................................................
.....................................................
Loading unloaded module list
..............................
This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
(a40.2580): Security check failure or stack buffer overrun - code c0000409 (first/second chance not available)
eax=00000001 ebx=00000000 ecx=00000007 edx=77cc4350 esi=00000000 edi=00000000
eip=62ae7666 esp=0b75e17c ebp=0b75e1a8 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
msvcr120!abort+0x28:
62ae7666 cd29            int     29h
0:068> kd: Reading initial command 'kb;q'
ChildEBP RetAddr  Args to Child              
0b75e178 62addc5f 935dda1f 00000000 00000000 msvcr120!abort+0x28
0b75e1a8 0b75e7d4 62a9b436 0b75e1dc 62a52aa5 msvcr120!terminate+0x33
WARNING: Frame IP not in any known module. Following frames may be wrong.
0b75e1ac 62a9b436 0b75e1dc 62a52aa5 00000000 0xb75e7d4
0b75e1b4 62a52aa5 00000000 62a59740 0b75e7d4 msvcr120!__FrameUnwindToState+0x89
0b75e1c8 62a52b33 00000000 00000000 00000000 msvcr120!_EH4_CallFilterFunc+0x12
0b75e1f4 62a5a0f3 62b1f7b8 62a4f7c6 0b75e324 msvcr120!_except_handler4_common+0x8e
0b75e214 77cd6152 0b75e324 0b75e7c4 0b75e344 msvcr120!_except_handler4+0x1e
0b75e238 77cd6124 0b75e324 0b75e7c4 0b75e344 ntdll!ExecuteHandler2+0x26
0b75e30c 77cc4266 0b75e324 0b75e344 0b75e324 ntdll!ExecuteHandler+0x24
0b75e30c 74cf28f2 0b75e324 0b75e344 0b75e324 ntdll!KiUserExceptionDispatcher+0x26
0b75e684 62a59339 e06d7363 00000001 00000003 KERNELBASE!RaiseException+0x62
0b75e6c4 6001821c 0b75e6e4 6004e1bc 946a8f2a msvcr120!_CxxThrowException+0x5b
0b75e6f8 60018042 0b75e720 946a8efa ffffffff mymodule!FunctionC+0x7c
0b75e730 60016544 946a8ece ffffffff 092889d8 mymodule!FunctionB+0x32
0b75e754 600166b8 00842338 6000588d 00000001 myothermodule!FunctionB+0x44

Из этого стека вы можете создать уникальное ведро, если вы берете, например, только ваши методы из стека и объединяете их в строку: " mymodule! FunctionC + 0x7c; mymodule! FunctionB + 0x32; myothermodule! FunctionB + 0x44 ». Чтобы это работало, вам нужно иметь доступ к вашему персональному серверу символов, используя либо переменную окружения _NT_SYMBOL_PATH, либо переключатель командной строки -y. В качестве альтернативы вы можете создать строку только из адресов возврата (второй столбец): " 62addc5f, 0b75e7d4,62a9b436,62a52aa5,62a52b33,62a5a0f3,77cd6152,77cd6124,77cc4266,74cf28f2,618,6000066001606162 1011 * "

1 голос
/ 07 января 2011

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

class Error {
    //...
    public: Error(string file, string line, string error) ;
};

#define ERROR(err) Error(__FILE__, __LINE__, err)
1 голос
/ 07 января 2011

IMO лучшее, что вы можете использовать, это идентификатор корзины из анализа дампа.Используйте правильно настроенные средства отладки для Windows (windbg), это можно сделать! Проанализировать -v и классифицировать ваши дампы в разные сегменты на основе идентификатора блока.Идентификатор корзины гарантируется, что если два дампа одинаковы, их идентификатор корзины будет одинаковым.Это решает часть головоломки.

Много раз два дампа с правами на одну и ту же проблему создают разные идентификаторы корзины (возможно, разница в версии, скажем, ваши 1.0 и 1.1 оба вылетали в одной точке).Вы можете использовать ошибочный модуль и подпись стека для сопоставления ошибок с одной и той же точки отказа.

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

1 голос
/ 06 января 2011

Здесь, в моем проекте, я использую адресную память Crash в качестве «уникального» идентификатора.

0 голосов
/ 07 января 2011

Я бы начал со сбора данных о том, как часто каждая функция в вашем коде «мигает» в трассировке стека отчетов о сбоях. Каждый отчет должен быть добавлен в какую-либо базу данных, и каждая функция должна быть проиндексирована, чтобы впоследствии можно было запрашивать, какие функции, по-видимому, аварийно завершают работу чаще других. (И, конечно, такие функции, как main (), будут присутствовать в каждом отчете, но это понятно).

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

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

0 голосов
/ 06 января 2011

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

...