Hello, lav03!
You wrote on Fri, 28 Nov 2003 11:09:21 GMT:
l> Распространять .pdb я не хочу. Как же мне тогда получить правильный l> список вызовов функций? Может через ассемблер в стек залезть? Не l> подскажет ли кто, где можно почитать о том, как получить информацию из l> стека с помощью ассемблера, где что там жранится и как его правильно l> просматривать. А уж получив адреса я по .map файлу смогу названия l> функций определить.
В общем-то, без pdb полноценно гулять по стеку, имхо, невозможно. Метод гуляния по стеку без pdb очень простой — предполагается, что компилятор в начале каждой функции генерирует некоторый пролог, формирующий так называемый stack frame:
push ebp
move ebp, esp
sub esp, local_vars_size
Соответственно, и сделать дамп стека не представляет особого труда (пример из какой-то статьи Питрека, хотя я его вроде под свои цели чуть-чуть переделывал):
void CCrashHandler::IntelStackWalk(PCONTEXT pContext)
{
_tprintf( _T("\r\nCall stack:\r\n") );
_tprintf( _T("Address Frame Logical addr Module\r\n") );
DWORD pc = pContext->Eip;
PDWORD pFrame, pPrevFrame;
pFrame = (PDWORD)pContext->Ebp;
do
{
TCHAR szModule[MAX_PATH] = _T("");
DWORD section = 0, offset = 0;
GetLogicalAddress((PVOID)pc, szModule, sizeof(szModule), section, offset);
_tprintf(_T("%08X %08X %04X:%08X %s\r\n"), pc, pFrame, section, offset, szModule);
pc = pFrame[1];
pPrevFrame = pFrame;
pFrame = (PDWORD)pFrame[0]; // precede to next higher frame on stack
if ((DWORD)pFrame & 3) // Frame pointer must be aligned on a
break; // DWORD boundary. Bail if not so.
if (pFrame <= pPrevFrame)
break;
// Can two DWORDs be read from the supposed frame address?
if (IsBadReadPtr(pFrame, sizeof(PVOID)*2))
break;
} while (1);
}
Однако все так здорово ровно до тех пор, пока компилятор не пользуется т.н. FPO — оптимизацию (Frame-Pointer Omission). Через код без кадров стека так просто не погуляешь, так что придется быть готовым к тому, что не всегда удастся сделать полноценный дамп стека (для увеличиния вероятности успеха можно выключить FPO при компиляции (опция /Oy- после опций оптимизации)), или использовать pdb (лучше ее слегка почикать с помощью /PDBSTRIPPED, если у тебя VC 7).
Best regards,
Sergey.
Posted via RSDN NNTP Server 1.8 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Hello, lav03!
You wrote on Wed, 26 Nov 2003 14:45:19 GMT:
PD>>> ИМХО что-то связано с imghelp.dll. Как бы мне ее VC7 не переписал при PD>>> установке.
L>> Точно! У меня тоже VC7 стоит. Я чейчас проверил — на VC7 работает. Это L>> что же тогда получается, мне сосвоей программой нужно и imghelp.dll от L>> VC7 распространять? А если я ее подменю, другие проги, юзающие старые L>> версии, отъедут?
l> На другом компе поробовал запустить программу — получил скудное l> содержание стека. Подсунул свою imagehelp.dll — тот же результат. Не l> работает.
А зачем тебе имена функций на компьютере клиента? Достаточно транслировать адреса в логические, а имена функций брать из map-файла на своей машине (ну, при этом, правда, придется хранить map-файлы и pdb для всех версий программы — зато pdb никому отдавать не придется). Или без map-файла — сразу бинарник+pdb в IDA грузить.
Best regards,
Sergey.
Posted via RSDN NNTP Server 1.8 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Hello, Блудов!
You wrote on Tue, 02 Dec 2003 02:57:35 GMT:
L>> А как вообще люди решают проблему, когда нужно локализовать ошибку при L>> возникновении исключения в распространяемом коммерческом продукте. Что, L>> PDB — файл распространяют?
БП> Вы читаете или нет, что вам люди отвечают???
БП> Писали же -- на клиентской машине нужно только БП> получить список адресов, в виде
БП> SomeDLL 0xFFF89898 БП> SomeDLL 0xFFF89A98 БП> SomeDLL 0xFFF89B98
Вообще-то речь о том и шла, что без pdb (хотя бы stripped) получить полный call stack иногда невозможно.
Best regards,
Sergey.
Posted via RSDN NNTP Server 1.8 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Дамп стека при возникновении исключения
От:
Аноним
Дата:
26.11.03 11:05
Оценка:
Люди, помогите. Замучался уже.
Работаю в MS VC++6.
Нужно в версии "release" с оптимизацией получить:
— список вызовов функций и их названия;
— номер последней выполненной строки программы;
— список загруженных модулей.
Все это нужно для локализации места ошибки после возникновения исключения (Structured Exceprion и C++).
Все, что мог — перепробовал. Топики на этом форуме перечитал. интернет обшарил. Пробовал использовать BugslayerUtil — не работает (точнее работает, но выдает только адреса и параметры, а остальную информацию — нет). Смотрел исходники, но, не смог найти причину.
AfxDumpSteck — не выдает функций моего приложения и номер строки.
Пробовал StackWalk — ничего не выходит.
Такое ощущение, что я что-то недопонимаю или не так делаю. Или что-то нужно правильно проинициализировать, прежде чем получить нужную мне информацию.
В общем, если кто знает, как мне помочь, помогите, пожалуйста. А то я на этом скончаюсь скоро.
Заранее благодарен, Александр.
26.11.03 14:14: Перенесено модератором из 'C/C++' — ПК
Здравствуйте, Вы писали:
> Работаю в MS VC++6. > Нужно в версии "release" с оптимизацией получить: > — список вызовов функций и их названия; <...> > Все, что мог — перепробовал.
Включить генерацию Debug Info не забыл?
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Здравствуйте, Вы писали:
>> Работаю в MS VC++6. >> Нужно в версии "release" с оптимизацией получить: >> — список вызовов функций и их названия; <...> >> Все, что мог — перепробовал.
ПК>Включить генерацию Debug Info не забыл?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Привет!
PD>lav03 wrote: >> >> ПК>Включить генерацию Debug Info не забыл? >> >> Нет,стоит.
PD>А Program Database ?
PD>-- PD>С наилучшими пожеланиями PD> Дворкин Павел
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Привет!
PD>lav03 wrote: >> >> ПК>Включить генерацию Debug Info не забыл? >> >> Нет,стоит.
PD>А Program Database ?
PD>-- PD>С наилучшими пожеланиями PD> Дворкин Павел
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Привет!
PD>lav03 wrote: >> >> А где же моя CTestErrDlg::OnButton1()
PD>А вообще-то файл .pdb есть в release версии ?
PD>-- PD>С наилучшими пожеланиями PD> Дворкин Павел
Есть.
Может какие-то директивы компилятора нужно добавить? Такое ощущение, что AfxDumpStack не всю инфу вкуривает. А тогда зачем она, такая дорогая, нужна? В МСДН ничего не написано ни про дополнительную инициализацию, ни про опции компиллета для этой функции. В дебаг-версии тоже самое примерно получается. Н понимаю
lav03 wrote: > > Здравствуйте, Pavel Dvorkin, Вы писали:
> Может какие-то директивы компилятора нужно добавить? Такое ощущение, что AfxDumpStack не всю инфу вкуривает. А тогда зачем она, такая дорогая, нужна? В МСДН ничего не написано ни про дополнительную инициализацию, ни про опции компиллета для этой функции. В дебаг-версии тоже самое примерно получается. Н понимаю
Я сейчас проверил у себя. Значит, так
Под VC6 Debug выдается Error 126 — (module not found, если это
GetLastError). После этого дамп, но без моих имен.
Под VC6 Release выдается одна строчка, не моя
Под VC7 Debug все замечательно.
Под VC7 Release тоже все прекрасно.
ИМХО что-то связано с imghelp.dll. Как бы мне ее VC7 не переписал при
установке.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Привет!
PD>lav03 wrote: >> >> Здравствуйте, Pavel Dvorkin, Вы писали:
>> Может какие-то директивы компилятора нужно добавить? Такое ощущение, что AfxDumpStack не всю инфу вкуривает. А тогда зачем она, такая дорогая, нужна? В МСДН ничего не написано ни про дополнительную инициализацию, ни про опции компиллета для этой функции. В дебаг-версии тоже самое примерно получается. Н понимаю
PD>Я сейчас проверил у себя. Значит, так
PD>Под VC6 Debug выдается Error 126 — (module not found, если это PD>GetLastError). После этого дамп, но без моих имен. PD>Под VC6 Release выдается одна строчка, не моя PD>Под VC7 Debug все замечательно. PD>Под VC7 Release тоже все прекрасно.
PD>ИМХО что-то связано с imghelp.dll. Как бы мне ее VC7 не переписал при PD>установке.
Точно! У меня тоже VC7 стоит. Я чейчас проверил — на VC7 работает. Это что же тогда получается, мне сосвоей программой нужно и imghelp.dll от VC7 распространять? А если я ее подменю, другие проги, юзающие старые версии, отъедут?
PD>-- PD>С наилучшими пожеланиями PD> Дворкин Павел
Здравствуйте, lav03, Вы писали:
L>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>Привет!
PD>>lav03 wrote: >>> >>> Здравствуйте, Pavel Dvorkin, Вы писали:
>>> Может какие-то директивы компилятора нужно добавить? Такое ощущение, что AfxDumpStack не всю инфу вкуривает. А тогда зачем она, такая дорогая, нужна? В МСДН ничего не написано ни про дополнительную инициализацию, ни про опции компиллета для этой функции. В дебаг-версии тоже самое примерно получается. Н понимаю
PD>>Я сейчас проверил у себя. Значит, так
PD>>Под VC6 Debug выдается Error 126 — (module not found, если это PD>>GetLastError). После этого дамп, но без моих имен. PD>>Под VC6 Release выдается одна строчка, не моя PD>>Под VC7 Debug все замечательно. PD>>Под VC7 Release тоже все прекрасно.
PD>>ИМХО что-то связано с imghelp.dll. Как бы мне ее VC7 не переписал при PD>>установке.
L>Точно! У меня тоже VC7 стоит. Я чейчас проверил — на VC7 работает. Это что же тогда получается, мне сосвоей программой нужно и imghelp.dll от VC7 распространять? А если я ее подменю, другие проги, юзающие старые версии, отъедут?
На другом компе поробовал запустить программу — получил скудное содержание стека. Подсунул свою imagehelp.dll — тот же результат. Не работает.
PD>>-- PD>>С наилучшими пожеланиями PD>> Дворкин Павел
Здравствуйте, Sergey, Вы писали:
S>А зачем тебе имена функций на компьютере клиента? Достаточно транслировать адреса в логические, а имена функций брать из map-файла на своей машине (ну, при этом, правда, придется хранить map-файлы и pdb для всех версий программы — зато pdb никому отдавать не придется). Или без map-файла — сразу бинарник+pdb в IDA грузить.
S>Best regards, S> Sergey.
Дело в том, что на другой машине она мне вообще не выдает даже адреса моей функции OnButton1.
lav03 wrote: > > Здравствуйте, Pavel Dvorkin, Вы писали: > PD>ИМХО что-то связано с imghelp.dll. Как бы мне ее VC7 не переписал при > PD>установке. > > Точно! У меня тоже VC7 стоит. Я чейчас проверил — на VC7 работает. Это что же тогда получается, мне сосвоей программой нужно и imghelp.dll от VC7 распространять? А если я ее подменю, другие проги, юзающие старые версии, отъедут?
Хуже. imghelp.dll не есть re-distributable .
Но вообще-то ИМХО нужно просто правильную версию сунуть в каталог, где
EXE. По общим правилам поиск сначала идет в этом каталоге, а потом в
system32 (см. LoadLibrary). Насколько я помню, к well-known dll она не
относится (а вообще-то проверь)
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Привет!
PD>lav03 wrote: >> >> Здравствуйте, Pavel Dvorkin, Вы писали: >> PD>ИМХО что-то связано с imghelp.dll. Как бы мне ее VC7 не переписал при >> PD>установке. >> >> Точно! У меня тоже VC7 стоит. Я чейчас проверил — на VC7 работает. Это что же тогда получается, мне сосвоей программой нужно и imghelp.dll от VC7 распространять? А если я ее подменю, другие проги, юзающие старые версии, отъедут?
PD>Хуже. imghelp.dll не есть re-distributable .
PD>Но вообще-то ИМХО нужно просто правильную версию сунуть в каталог, где PD>EXE. По общим правилам поиск сначала идет в этом каталоге, а потом в PD>system32 (см. LoadLibrary). Насколько я помню, к well-known dll она не PD>относится (а вообще-то проверь)
PD>-- PD>С наилучшими пожеланиями PD> Дворкин Павел
Сунул. Не работает.
Вот гадость какая. Вся идея рушится. А так хотелось сделать хорошо.
Уверен, что именно ту, что нужно сунул ?
Эта библиотека записывается в system32 при инсталляции VC (ИМХО). Я бы
на твоем месте поискал бы ее в system32 машины, на которой VC7 никогда
не ставился.
Работало же оно в конце концов до того, как VC7 на свет появился.
AfxDump.. ИМХО еще в 4.2 была, а то и раньше.
Ха! Я понял. AfxDumpStack() без файла .pdb не работает (точнеее работает, но не так). Прчем, интересно получается.
Если я имею .pdb, я получу примерно такой дамп:
где foo — моя функция, где произошло, в данном случае структурнре, исключение, а CEhsTerminalErrHandler::HandleStructuredException() и CEhsTerminalErrHandler::MakeStructuredExceptionReport() вызываются из foo() для обработки исключения.
Если же программа не находит .pdb файл, дамп содержит меньше строк. А самое обидное, что в нем нет адресов функций:
0040157F: \SUPERPUPS\Guest\1\ErrHndlTest.exe! CEhsTerminalErrHandler::HandleStructuredException + 31 bytes
0040195D: \SUPERPUPS\Guest\1\ErrHndlTest.exe! foo + 349 bytes
Причем, такая фича имеет место, если AfxDumpStack() вызвана в теле ф-ции
CEhsTerminalErrHandler::MakeStructuredExceptionReport().
Но, если AfxDumpStack() вызвать непосредственно из foo, то строки
0040157F: \SUPERPUPS\Guest\1\ErrHndlTest.exe! <no symbol>
0040195D: \SUPERPUPS\Guest\1\ErrHndlTest.exe! <no symbol>
соотсет-щие ф-циям CEhsTerminalErrHandler::HandleStructuredException() и foo() появятся.
AfxDumpStack() использует API для "прогулок по стеку". Может там и есть где-то ошибка, но, посмотрев исходник, почитав описания ф-ций и различных структур, ей испольуемых, для меня работа со стеком с помощью API не стала много прозрачней. По крайней мере ошибку в исходнике я не в состоянии найти.
Распространять .pdb я не хочу. Как же мне тогда получить правильный список вызовов функций? Может через ассемблер в стек залезть? Не подскажет ли кто, где можно почитать о том, как получить информацию из стека с помощью ассемблера, где что там жранится и как его правильно просматривать. А уж получив адреса я по .map файлу смогу названия функций определить.
lav03 wrote: > > Здравствуйте, Pavel Dvorkin, Вы писали: > > Ха! Я понял. AfxDumpStack() без файла .pdb не работает
Именно так. Я полагал, что ты это знаешь.
> > Распространять .pdb я не хочу. Как же мне тогда получить правильный список вызовов функций?
Никак. Как говорил один литературный герой, "при наличии отсутствия".
Именно в .pdb (можно еще в .dbg, но я не знаю, как их делать) и лежит
вся требуемая информация.
>Может через ассемблер в стек залезть? Не подскажет ли кто, где можно почитать о том, как получить информацию из стека с помощью ассемблера, где что там жранится и как его правильно просматривать. А уж получив адреса я по .map файлу смогу названия функций определить.
Хм, а чем тебе map файл лучше pdb ?
А насчет того, что хранится в стеке — ответ прост. Адреса возвратов,
локальные переменные, фактические парметры и фреймы SEH. В стековом
порядке
Hello, lav03!
You wrote on Fri, 28 Nov 2003 12:46:10 GMT:
l> Понятно. А что это за ф-ция GetLogicalAddress(..)? Это не апишная, ее в l> МСДМН нет.
Оно в старом MSDN было, за 2000 год вроде, в статьях из MSJ.
l> Ты не мог бы мне ее код дать?
//==============================================================================
// Given a linear address, locates the module, section, and offset containing
// that address.
//
// Note: the szModule paramater buffer is an output buffer of length specified
// by the len parameter (in characters!)
//==============================================================================
BOOL CCrashHandler::GetLogicalAddress(PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD& offset)
{
MEMORY_BASIC_INFORMATION mbi;
if (!VirtualQuery(addr, &mbi, sizeof(mbi)))
return FALSE;
DWORD hMod = (DWORD) mbi.AllocationBase;
if (!GetModuleFileName((HMODULE) hMod, szModule, len))
return FALSE;
// Point to the DOS header in memory
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER) hMod;
// From the DOS header, find the NT (PE) header
PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS) (hMod + pDosHdr->e_lfanew);
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION (pNtHdr);
DWORD rva = (DWORD) addr - hMod; // RVA is offset from module load address
// Iterate through the section table, looking for the one that encompasses
// the linear address.for (unsigned i = 0; i < pNtHdr->FileHeader.NumberOfSections; i++, pSection++)
{
DWORD sectionStart = pSection->VirtualAddress;
DWORD sectionEnd = sectionStart + max(pSection->SizeOfRawData, pSection->Misc.VirtualSize);
// Is the address in this section???if ((rva >= sectionStart) && (rva <= sectionEnd))
{
// Yes, address is in the section. Calculate section and offset,
// and store in the "section" & "offset" params, which were
// passed by reference.
section = i + 1;
offset = rva - sectionStart;
return TRUE;
}
}
return FALSE; // Should never get here!
}
Best regards,
Sergey.
Posted via RSDN NNTP Server 1.8 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
В моем обработчике SE вызывается IntelStackWalk(pExceptionInfo->ContextRecord),
где pExceptionInfo — это e.m_ExceptionRecord (не буду писать подробно). В общем, e.m_ExceptionRecord инициализируется в конструкторе CStructuredException. Все, как у Рихтера.
IntelStackWalk выдает прекрасный дамп, где самая первая строчка — адрес (естест-но со смещением) ф-ции
CSimpleString.SetAt(..);
Затемм идет адрес foo(), а потом OnBnClickedButton1().
Я об этом и мечтал!!!
Но если я изменю код:
void CErrHndlTestDlg::OnBnClickedButton1()
{
try{
int res = foo();
}
catch(CMemoryException e) {...}
catch(CStructuredException e) {...}
}
int foo()
{
try{
throw new CMemoryException; // С++ исключение
}
catch(CMemoryException e) {...}
catch(CStructuredException e) {...}
return 0;
}
и в обработчике для CMemoryException получу контекст-рекорд
Hello, lav03!
You wrote on Fri, 28 Nov 2003 18:00:36 GMT:
l> и в обработчике для CMemoryException получу контекст-рекорд
l> CONTEXT Context; l> Context.ContextFlags = CONTEXT_FULL; l> GetThreadContext(m_hThread, &Context); l> IntelStackWalk(&Context);
l> первый адрес в дампе получаю какой — то бещеный:
l> Address Frame Logical addr Module l> 7FFE0304 0012FA14 0000:00000000
Это адрес в NTDLL.DLL — функция ZwGetContextThread. А что ты там ожидал увидеть?
l> а следующий адрес указывает даже не на мою foo(), а на l> OnBnClickedButton1().
А что отладчик показывает в стеке?
l> Такое ощущение, что фрейм не формируется.
Функция GetThreadContext действительно без фрейма, поэтому ее в дампе и не будет. А вообще отладчиком глянь.
l> Делел в VC++7. Опцию /Oy отключил.
l> Не пойму разницы. По крайней мере адрес возврата из foo() должен быть в l> стеке
У тебя исключение где поймалось — в OnBnClickedButton1 или в foo? Судя по приведенному коду, оно вообще ловиться не должно, поскольку кидаешь ты CMemoryException*, а ловишь CMemoryException.
Best regards,
Sergey.
Posted via RSDN NNTP Server 1.8 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Sergey, Вы писали:
l>> Не пойму разницы. По крайней мере адрес возврата из foo() должен быть в l>> стеке
S>У тебя исключение где поймалось — в OnBnClickedButton1 или в foo? Судя по приведенному коду, оно вообще ловиться не должно, поскольку кидаешь ты CMemoryException*, а ловишь CMemoryException.
S>Best regards, S> Sergey.
Нет, на самом деле я ловлю CMemoryException*, это описка. И оно ловится именно в foo(), только вот foo(), почему-то, в стеке не присутствует во время снятия списка вызовов. Усли убрать try...catch из foo(), то оно поймается в OnBnClickedButton1() и адрес этой OnBnClickedButton1() будет отсутствовать в дампе, а следующим после
7FFE0304 0012FA14 0000:00000000 будет адрес _AfxDispatchCmdMsg.
Не понимаю, почему ф-ция, из которой выброшено C++ исключение отсутствует в списке вызовов, ведь на момент снятия дампа мы из ее тела еще не вышли.
А как вообще люди решают проблему, когда нужно локализовать ошибку при возникновении исключения в распространяемом коммерческом продукте. Что, PDB — файл распространяют?
Hello, lav03!
You wrote on Mon, 01 Dec 2003 08:57:34 GMT:
l> Нет, на самом деле я ловлю CMemoryException*, это описка. И оно ловится l> именно в foo(), только вот foo(), почему-то, в стеке не присутствует во l> время снятия списка вызовов. Усли убрать try...catch из foo(), то оно l> поймается в OnBnClickedButton1() и адрес этой OnBnClickedButton1() будет l> отсутствовать в дампе, а следующим после 7FFE0304 0012FA14 0000:00000000 l> будет адрес _AfxDispatchCmdMsg. Не понимаю, почему ф-ция, из которой l> выброшено C++ исключение отсутствует в списке вызовов, ведь на момент l> снятия дампа мы из ее тела еще не вышли.
Эта фигня происходит из-за того, что функция ZwGetContextThread скомпилена без кадра стека. Поэтому IntelStackWalk хватает кадр предыдущей функции (foo), из которого вытаскивает адрес возврата на OnBnClickedButton1(). В результате foo в дамп не попадает.
Best regards,
Sergey.
Posted via RSDN NNTP Server 1.8 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Hello, lav03!
You wrote on Mon, 01 Dec 2003 11:46:06 GMT:
l> А как вообще люди решают проблему, когда нужно локализовать ошибку при l> возникновении исключения в распространяемом коммерческом продукте.
А так и решают С дизассемблером в руках
l> Что, PDB — файл распространяют?
Не поможет. Еще pdb'шки для системных dll'ек нужны, а фиг ты энд-юзера заставишь их установить.
Best regards,
Sergey.
Posted via RSDN NNTP Server 1.8 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, lav03, Вы писали:
L>А как вообще люди решают проблему, когда нужно локализовать ошибку при возникновении исключения в распространяемом коммерческом продукте. Что, PDB — файл распространяют?
Вы читаете или нет, что вам люди отвечают???
Писали же -- на клиентской машине нужно только
получить список адресов, в виде
, затем список загруженных DLL вместе с их версиями,
все это отсылается разработчику и на месте переводится
в удобочитаемый код.
Как следствие, приходится не только хранить все
версии своей программы с PDB-шниками, но еще и все
версии всех windows, тоже с PDB-шниками (слава WMWare!)
Здравствуйте, Sergey, Вы писали:
S>Вообще-то речь о том и шла, что без pdb (хотя бы stripped) получить полный call stack иногда невозможно.
Согласен. Мне пришлось запретить компилятору выкидывать стековые фреймы.
С inline-ми не помогает, но более-менее приличную информацию все же
можно собрать.
Здравствуйте, Sergey, Вы писали:
S>Hello, lav03! S>You wrote on Mon, 01 Dec 2003 08:57:34 GMT:
l>> Нет, на самом деле я ловлю CMemoryException*, это описка. И оно ловится l>> именно в foo(), только вот foo(), почему-то, в стеке не присутствует во l>> время снятия списка вызовов. Усли убрать try...catch из foo(), то оно l>> поймается в OnBnClickedButton1() и адрес этой OnBnClickedButton1() будет l>> отсутствовать в дампе, а следующим после 7FFE0304 0012FA14 0000:00000000 l>> будет адрес _AfxDispatchCmdMsg. Не понимаю, почему ф-ция, из которой l>> выброшено C++ исключение отсутствует в списке вызовов, ведь на момент l>> снятия дампа мы из ее тела еще не вышли.
S>Эта фигня происходит из-за того, что функция ZwGetContextThread скомпилена без кадра стека. Поэтому IntelStackWalk хватает кадр предыдущей функции (foo), из которого вытаскивает адрес возврата на OnBnClickedButton1(). В результате foo в дамп не попадает.
S>Best regards, S> Sergey.
А ведь если отключить оптимизацию, то foo() попадает в дамп. Значит в этом случае кадр стека все же формируется?
Можно ли как нибудь заставить функцию кадр стека формироваться, обхитрить?
Hello, lav03!
You wrote on Tue, 02 Dec 2003 08:41:11 GMT:
S>> Эта фигня происходит из-за того, что функция ZwGetContextThread S>> скомпилена без кадра стека. Поэтому IntelStackWalk хватает кадр S>> предыдущей функции (foo), из которого вытаскивает адрес возврата на S>> OnBnClickedButton1(). В результате foo в дамп не попадает.
l> А ведь если отключить оптимизацию, то foo() попадает в дамп.
Не верю. Ты наверное что-то перепутал.
l> Значит в этом случае кадр стека все же формируется?
Как это он сформируется для функции из ntdll? Я дизассемблером смотрел — нет там никакой установки ebp, почти сразу int 2E идет.
l> Можно ли как нибудь заставить функцию кадр стека формироваться, обхитрить?
Ну так я говорил уже — опция компилятора /Oy- после опций оптимизации, и все будет почти как надо.
Best regards,
Sergey.
Posted via RSDN NNTP Server 1.8 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[22]: Дамп стека при возникновении исключения
От:
Аноним
Дата:
03.12.03 09:04
Оценка:
Здравствуйте, Sergey, Вы писали:
S>Hello, lav03! S>You wrote on Tue, 02 Dec 2003 08:41:11 GMT:
S>>> Эта фигня происходит из-за того, что функция ZwGetContextThread S>>> скомпилена без кадра стека. Поэтому IntelStackWalk хватает кадр S>>> предыдущей функции (foo), из которого вытаскивает адрес возврата на S>>> OnBnClickedButton1(). В результате foo в дамп не попадает.
l>> А ведь если отключить оптимизацию, то foo() попадает в дамп. S>Не верю. Ты наверное что-то перепутал.
l>> Значит в этом случае кадр стека все же формируется? S>Как это он сформируется для функции из ntdll? Я дизассемблером смотрел — нет там никакой установки ebp, почти сразу int 2E идет.
l>> Можно ли как нибудь заставить функцию кадр стека формироваться, обхитрить? S>Ну так я говорил уже — опция компилятора /Oy- после опций оптимизации, и все будет почти как надо.
S>Best regards, S> Sergey.
Понятно, спасибо.
На счет отключения оптимизации я , кажется, действительно перепутал.
Но я пробовал и с /Oy и без нее, результат почему-то одинаков. Не работает. Я даже создал новцй проект для чистоты эксперимента.
Бог с ней с ZwGetContextThread. Мне не понятно, почему в моих OnBnClickedButton1() b foo() кадр стека формируется, а в IntelStackWalk() — нет, ведь все же они в одном проекте с одинаковыми опциями компилчтора скомпилированы.
Hello, !
You wrote on Wed, 03 Dec 2003 09:04:47 GMT:
> Понятно, спасибо.
Что-то непохоже
> На счет отключения оптимизации я , кажется, действительно перепутал.
> Но я пробовал и с /Oy и без нее, результат почему-то одинаков.
Значит, FPO-оптимизация и так не используется.
> Не работает. Я даже создал новцй проект для чистоты эксперимента.
Что конкретно не работает? foo в трэйс не попадает? Так ведь и не должно.
> Бог с ней с ZwGetContextThread. Мне не понятно, почему в моих > OnBnClickedButton1() b foo() кадр стека формируется, а в IntelStackWalk() > — нет, ведь все же они в одном проекте с одинаковыми опциями компилчтора > скомпилированы.
Код покажи. И дизассемблированный (начало функции IntelStackWalk) в том числе, а то опять не поверю, потому что в функции IntelStackWalk, IMHO, достаточно локальных переменных для того, чтобы FPO-оптимизация была невыгодной.
Best regards,
Sergey.
Posted via RSDN NNTP Server 1.8 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.