我们有一个通过 COM+ 在 Windows 2003 服务器上运行的本机 C++ 应用程序。我最近从事件查看器中注意到它抛出异常,特别是 C0000005 异常,根据http://blogs.msdn.com/calvin_hsia/archive/2004/06/30/170344.aspx表示该过程正在尝试写入不在其地址空间内的内存,也就是访问冲突。
事件查看器中的条目提供了一个调用堆栈:
LibFmwk!UTIL_GetDateFromLogByDayDirectory(char const *,class utilCDate &) + 0xa26c LibFmwk!UTIL_GetDateFromLogByDayDirectory(char const *,class utilCDate &) + 0x8af4 LibFmwk!UTIL_GetDateFromLogByDayDirectory(char const *,class utilCDate &) + 0x13a1 LibFmwk:::! )const + 0x1070 LibFmwk!utilCLogController::GetFLFInfoLevel(void)const + 0x186
现在,我知道它给了我要查看的方法名称,但我感觉每行末尾的地址(例如 + 0xa26c)试图将我指向该方法中的特定行或指令。
所以我的问题是:
- 有谁知道我如何使用这个地址或调用堆栈中的任何其他信息来确定代码中的哪一行?
- 有没有我可以阅读以更好地理解调用堆栈的资源,
- 是否有任何免费软件/开源工具可以帮助分析调用堆栈,可能通过附加到调试符号文件和/或二进制文件?
编辑:根据要求,这是似乎导致问题的方法:
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 和运算符的地址确实使它看起来相当可疑。
我们似乎遇到的另一个问题是,这只发生在生产系统上,我们永远无法在我们的测试系统或开发系统上重现它,这将允许我们附加调试器。
非常感激!安迪