У нас есть собственное приложение на C++, запущенное через COM + на сервере Windows 2003. Недавно я заметил из средства просмотра событий, что его исключения исключения, в частности исключение C0000005, которое, согласно http://blogs.msdn.com/calvin_hsia/archive/2004/06/30/170344.aspx, означает, что процесс пытается записать в память не в пределах своего адресного пространства, например, нарушения прав доступа.Как читать стек вызовов?
Запись в окне просмотра событий предоставляет стек вызовов:
LibFmwk UTIL_GetDateFromLogByDayDirectory (символ сопз *, класс utilCDate &) + 0xa26c LibFmwk UTIL_GetDateFromLogByDayDirectory (символ сопз *, класс utilCDate &) + 0x8af4 ! LibFmwk! UTIL_GetDateFromLogByDayDirectory (символ сопз *, класс utilCDate &) + 0x13a1 LibFmwk! utilCLogController :: GetFLFInfoLevel (аннулируются) Const + 0x1070 LibFmwk! utilCLogController :: GetFLFInfoLevel (аннулируются) Const + 0x186
Теперь я понимаю, что он дает мне имена методов, чтобы посмотреть, но у меня возникает ощущение, что адрес в конце каждой строки (например, + 0xa26c) пытается указать мне конкретную строку или инструкцию в этом методе.
Так что мои вопросы:
- Кто-нибудь знает, как я мог бы использовать этот адрес или любую другую информацию в стеке вызовов, чтобы определить, какую строку в коде его падение над на?
- Есть ли там какие-либо ресурсы, которые я мог бы читать, чтобы лучше понимать стеки вызовов,
- Есть ли какие-либо инструменты для бесплатного использования/раскрытия, которые могли бы помочь в анализе стека вызовов, возможно, путем присоединения к файлу символов отладки и/или двоичным файлам ?
Edit: В соответствии с просьбой, вот метод, который, как представляется, вызывает проблему:
BOOL UTIL_GetDateFromLogByDayDirectory(LPCSTR pszDir, utilCDate& oDate)
{
BOOL bRet = FALSE;
if ((pszDir[0] == '%') &&
::isdigit(pszDir[1]) && ::isdigit(pszDir[2]) &&
::isdigit(pszDir[3]) && ::isdigit(pszDir[4]) &&
::isdigit(pszDir[5]) && ::isdigit(pszDir[6]) &&
::isdigit(pszDir[7]) && ::isdigit(pszDir[8]) &&
!pszDir[9])
{
char acCopy[9];
::memcpy(acCopy, pszDir + 1, 8);
acCopy[8] = '\0';
int iDay = ::atoi(&acCopy[6]);
acCopy[6] = '\0';
int iMonth = ::atoi(&acCopy[4]);
acCopy[4] = '\0';
int iYear = ::atoi(&acCopy[0]);
oDate.Set(iDay, iMonth, iYear);
bRet = TRUE;
}
return (bRet);
}
Это код, написанный 10 лет назад членом нашей компании который уже давно ушел, поэтому я не могу точно знать, что это делает, но я знаю, что он участвует в процессе переименования каталога журнала с «Сегодня» на конкретную дату, например % 20090329. Индексирование массива, memcpy и адрес операторов делают его довольно подозрительным.
Другая проблема, которая, как нам кажется, заключается в том, что это происходит только в производственной системе, мы никогда не могли воспроизвести ее на наших тестовых системах или в системах разработки, что позволило бы нам подключить отладчик.
Большое спасибо! Энди
Если вы создаете с помощью отладочных символов, вы можете получить фактический номер строки, а не смещение байта. –
Спасибо, что указали это. –
Итак, вы уверены, что переданный pszDir имеет длину не менее 10 символов? Это, безусловно, сбой, если это не так. – jussij