如何找到仅出现在日志中的第一手异常?
How to find the first hand exception that only shows up in the log?
我在我们的产品中偶然发现了一些奇怪的行为 - 每隔一段时间(从几分钟到几天不等),我们的日志(我们通常将特定日志写入的一个简单的 .txt 文件)显示此消息:
******************************************************
****** Warning - First Chance Exception Caught! ******
******************************************************
Process Name : C:\OurApp.exe
Process ID : 27396
Thread ID : 21616
Debugger Time : 11:45:34.073 24/10/2017
Exception Code : 0xC0000005 - EXCEPTION_ACCESS_VIOLATION
Exception Desc : The thread tried to read from or write to a virtual address for which it does not have the appropriate access.
Extended Desc : The thread attempted to read inaccessible data.
Extended Desc 2 : Virtual address of inaccessible data 0xC
Exception Address : 0x100517E2
Resolved Address : <no module> (No symbol) [0x100517E2]
Stack Trace :
<no module> (No symbol) [0x85C5A7D8]
Frames below may be incorrect and/or missing (symbol not found)
******************************************************
除此之外,没有明显的特殊行为 - 它最初被报告为崩溃,但显然它没有崩溃,只是不时将其打印到日志中。它不是我们的日志之一,并且此警告不在任何代码文件中(我扫描了整个存储库,而不仅仅是特定项目)。无论日志级别是多少,它都会被打印出来。
我也无法在任何文档中找到此消息(我们的应用程序是用 C# 编写的,但可能有用 C++/Java 编写的导入模块),所以到目前为止我不确定如何找到罪魁祸首,我该如何阻止这种情况的发生。
我确定 OurApp.exe 生成的进程将此写入日志(使用 procmon 检查)。
任何想法如何找到它发生的原因以及如何阻止它都将不胜感激!
只要是第一次例外,并且没有相关的阴性症状,就可能没问题。
这是一个 SEH(结构化异常处理)"First Chance Exception",它是 Windows 上的操作系统功能。
使用 SEH,异常过滤器(通常是 C 或 C++ 代码)可以选择在不展开堆栈的情况下尝试从 "first chance" 异常中恢复。
只有在没有异常过滤器提供恢复时,异常才会像 C++、Java 或 C# 异常一样最终得到 "thrown"。
OS 级代码(或本机代码库)使用首次 0xC0000005
异常作为首次使用时初始化代码或数据的一种方式是很正常的。例如,它们用于延迟加载 DLL - 第一次调用函数时,您会遇到第一次异常,异常过滤器会加载 DLL,然后告诉 OS 重试。
心理调试:
您可能在某处有执行此操作的代码:
intptr LogException(LPEXCEPTION_POINTERS pep){
// Log the exception
return EXCEPTION_CONTINUE_SEARCH;
}
__try{
// Some code
}
__except(LogException(GetExceptionInformation())){}
您可以改进 "LogException" 以从异常记录中提取更多信息。
您已经在检索一些扩展数据。
在您的特定情况下,故障地址似乎是 0xC。这可能是一个哨兵值,但它看起来也很可疑,就像您通过空指针调用了 C++ 对象一样。
进一步思考,没有模块和符号的事实表明这是属于 Java 或 C# 的 JIT-ed 代码。如果是这种情况,您可能在本应使用数组或结构时传入或返回空指针,可能是在 JNI 或 P/Invoke 方法中(但也可能是 COM 方法)。
我在我们的产品中偶然发现了一些奇怪的行为 - 每隔一段时间(从几分钟到几天不等),我们的日志(我们通常将特定日志写入的一个简单的 .txt 文件)显示此消息:
******************************************************
****** Warning - First Chance Exception Caught! ******
******************************************************
Process Name : C:\OurApp.exe
Process ID : 27396
Thread ID : 21616
Debugger Time : 11:45:34.073 24/10/2017
Exception Code : 0xC0000005 - EXCEPTION_ACCESS_VIOLATION
Exception Desc : The thread tried to read from or write to a virtual address for which it does not have the appropriate access.
Extended Desc : The thread attempted to read inaccessible data.
Extended Desc 2 : Virtual address of inaccessible data 0xC
Exception Address : 0x100517E2
Resolved Address : <no module> (No symbol) [0x100517E2]
Stack Trace :
<no module> (No symbol) [0x85C5A7D8]
Frames below may be incorrect and/or missing (symbol not found)
******************************************************
除此之外,没有明显的特殊行为 - 它最初被报告为崩溃,但显然它没有崩溃,只是不时将其打印到日志中。它不是我们的日志之一,并且此警告不在任何代码文件中(我扫描了整个存储库,而不仅仅是特定项目)。无论日志级别是多少,它都会被打印出来。
我也无法在任何文档中找到此消息(我们的应用程序是用 C# 编写的,但可能有用 C++/Java 编写的导入模块),所以到目前为止我不确定如何找到罪魁祸首,我该如何阻止这种情况的发生。
我确定 OurApp.exe 生成的进程将此写入日志(使用 procmon 检查)。
任何想法如何找到它发生的原因以及如何阻止它都将不胜感激!
只要是第一次例外,并且没有相关的阴性症状,就可能没问题。
这是一个 SEH(结构化异常处理)"First Chance Exception",它是 Windows 上的操作系统功能。
使用 SEH,异常过滤器(通常是 C 或 C++ 代码)可以选择在不展开堆栈的情况下尝试从 "first chance" 异常中恢复。
只有在没有异常过滤器提供恢复时,异常才会像 C++、Java 或 C# 异常一样最终得到 "thrown"。
OS 级代码(或本机代码库)使用首次 0xC0000005
异常作为首次使用时初始化代码或数据的一种方式是很正常的。例如,它们用于延迟加载 DLL - 第一次调用函数时,您会遇到第一次异常,异常过滤器会加载 DLL,然后告诉 OS 重试。
心理调试:
您可能在某处有执行此操作的代码:
intptr LogException(LPEXCEPTION_POINTERS pep){
// Log the exception
return EXCEPTION_CONTINUE_SEARCH;
}
__try{
// Some code
}
__except(LogException(GetExceptionInformation())){}
您可以改进 "LogException" 以从异常记录中提取更多信息。
您已经在检索一些扩展数据。
在您的特定情况下,故障地址似乎是 0xC。这可能是一个哨兵值,但它看起来也很可疑,就像您通过空指针调用了 C++ 对象一样。
进一步思考,没有模块和符号的事实表明这是属于 Java 或 C# 的 JIT-ed 代码。如果是这种情况,您可能在本应使用数组或结构时传入或返回空指针,可能是在 JNI 或 P/Invoke 方法中(但也可能是 COM 方法)。