但是,当它崩溃时,我会得到这个“MicroSoft Visual Studio”弹出窗口,其中显示:
在NIMCAsst.exe中未处理的异常0x7c809e8a:0xC0000005:访问位置0x154c6000时违规。
上述信息是否有助于了解崩溃发生的地方?是否有任何软件可以告诉我特定的内存地址由代码中的哪个变量持有。
如果有时您无法捕获异常,那么您只能逐行检查代码,这非常不愉快,但我敢打赌,这是您的代码而不是MFC(我的错误总是如此)。请特别注意您如何使用内存以及将什么传递给MFC函数。
这个崩溃是否可以清晰地再现?
如果是的话,使用日志文件!您应该使用日志文件并添加一些语句,仅记录传递的源文件/行号。从入口点(主事件处理程序)和最常见的执行路径开始添加几个语句。在崩溃后检查日志文件中的最后一个条目。然后沿着必须通过的路径/路径添加新条目等。通常,在进行几次迭代后,您将找到故障点。在长时间等待的情况下,日志文件可能会变得非常庞大,每次迭代都需要另外18小时。您可能需要添加一些旋转日志文件等技术。但是,使用此技术,我能够找到一些可比较的错误。
还有一些问题:
您的应用程序是否是多线程的?
它是否使用任何不由stl或可比容器管理的数组(例如,它是否使用C-Strings、C/C++-Arrays等)?
这是可能导致内存泄漏的原因,有各种博客可以教你如何检查应用程序中的内存泄漏,你只需从Windows任务管理器中观察进程的物理内存,就可以找到某个阶段内存不断增加并耗尽内存。你也可以尝试使用windbg工具来识别代码中的内存泄漏。我没有使用过这个工具,只是提供一些提示。
尝试将调试器附加到进程上,并让调试器在访问违规时中断。
如果无法实现,则使用名为“用户模式进程转储程序”的工具,在发生访问违规的点创建进程的内存转储。您可以在此处找到该工具进行下载:
如何运作:您可以在每个进程(或可选的系统范围)上配置规则,当它检测到一系列异常中的任何一个时,工具就会创建一个迷你转储或完整转储。其中之一是访问冲突。在完成转储后,应用程序会像往常一样继续运行(因此,如果访问违规未经处理,则会看到此对话框)。最后,需要警告的是,使用WinDbg调试访问冲突可能是一个相当复杂和繁琐的过程 - 如果您可以通过其他方式获取堆栈跟踪,则建议您首先尝试该方法。
typedef enum {
WM_UPDATE_GUI
}WM_MY_MSG
// register function callback to a message
BEGIN_MESSAGE_MAP(CMyDlg, CDlgBase)
ON_MESSAGE(WM_UPDATE_GUI, OnUpdateGui)
END_MESSAGE_MAP()
// For this example - function that is not invoked in the Main Thread:
void CMyDlg::OnTimer()
{
CString str_to_GUI("send me to gui"); // send string to gui
// Update_GUI(str_to_GUI); // crashed
::PostMessage(hWnd, MyMsg::WM_UPDATE_GUI, (WPARAM)&str_to_GUI, 0);
}
HRESULT CMyDlg::OnUpdateGui(WPARAM wParam, LPARAM lParam)
{
CString str = *(CString*)wParam; // get the string from the posted message
Update_GUI(str);
return S_OK;
}