正在测试程序的功能, 用VS2019开着调试版跑起来. 发现程序关闭后, 在VS2019的输出窗口发现了C++异常的信息, 还不是一条.
虽然不影响程序的运行, 但是心里膈应.
这种异常发生了, 但是没被VS2019断下来, 说明这4个C++异常是在工程中被try-catch住的.
我现在这个程序, 主动使用try-catch的地方不多. 如果在每个try-catch住的地方下断点倒是可以.
但是为了普遍性, 还是要找出一种不依赖断点无脑排错的调试方法.
将debug版编译好, 用IDA带着跑起来.
用IDA载入EXE时, 因为是载入的Debug版程序, 连同PDB一起载入.
选择本地调试器
跑起来.
进行一样的操作, 发现IDA断住异常了:)
按确定后, 让程序自然暂停住.
打开栈调用链窗口
因为出了异常, 栈调用链不是很准.
但是能看到最上层的函数是COrderOperation::static_thread_dispatch().
那现在就可以有的放矢了, 关掉IDA.
只在COrderOperation::static_thread_dispatch()上下断点.
然后重新用VS2019跑程序, 到了发现报错的疑似顶层函数, 步入, 然后步过, 看看执行过那步, 会在VS2019输出窗口显示被捕获的异常信息.
如此这般, 就会很快缩小排查范围. 最后定位并修复问题.
我这里发下的问题是, 删除文件的函数做了try-catch, 如果删除了不存在的文件, 就会抛异常, 并被函数内的catch捕获住. 修正如下:
bool CFileOperation::Delete(CString sPathName)
{
try {
// 如果文件存在, 才删除, 防止出异常.
// 虽然这里被catch住了, 总的来说不好
if (!this->IsFileExist(sPathName))
{
return true;
}
DoDelete(sPathName);
} catch (CFExeption* e) {
m_sError = e->GetErrorText();
m_dwError = e->GetErrorCode();
delete e;
if (m_dwError == 0) {
return true;
}
return false;
}
return true;
}
虽然被try-catch住的异常, 不会引起程序的功能出问题. 但是也说明可能哪里出了问题, 如果能在逻辑上将异常搞定, 让他不出异常, 感觉更好一点.
修正完后, 又跑了一次, 程序退出后, 在VS2019的输出窗口没有任何发生c++异常的提示信息了:P
又想了一下, 既然是自己try-catch, 那么自然知道是哪里catch的, 为何不在catch中, 用框架提供的功能, 整点动静出来, 这样, 也不用第三方调试器辅助调试了.
在VS2019Debug版程序退出后, 如果在输出窗口看到自己catch住的打印信息的输出, 双击就可以定位到catch住异常的地方了.
这属于自己编码不规范引起的问题.
当然, 发现异常后, 如果有可能修复, 还是要修复.
这种用IDA来辅助定位问题的方法, 对于自己的工程可能有点脱裤子放屁的感觉.
但是对于自己接手维护的不规范工程(e.g. 不是自己写的工程(刚接手, 还没深入理解), 开源工程(代码行数大, 看不过来, 刚接触的工程, 逻辑理解的有点懵懂), 遗留的烂工程(可能就是自己以前写的工程)), 还是管点用.