高分求解: 程序异常退出,如何捕捉,知道是哪里原因?

时间:2021-12-31 07:17:14
   我的一个VC/MFC程序,使用了IOCP进行TCP/IP通讯,但在大量通讯中进行了
几十万次通讯后,没有任何征兆和想象,随机的会突然退出. 程序在运行过程中,
我通过任务管理器看这个程序的内存使用,CPU占用,线程数,句柄等各项指标都正常.
   有高手,能出主意,我该如何可以知道问题在哪里吗?
   

15 个解决方案

#1




崩溃?

#2


1:写程序日志
2:把程序在debug状态下运行,看出错的时候是否能断点到你出错的地方

#3



LPTOP_LEVEL_EXCEPTION_FILTER g_ExceptionFilter = NULL;
LONG WINAPI MyExceptionFilter (struct _EXCEPTION_POINTERS* lpExceptionInfo)
{
#ifdef   _DEBUG   
DebugBreak();   
#endif   

FILE *fp =fopen("d:\\error.dat","wb");
struct _EXCEPTION_RECORD* pER = lpExceptionInfo->ExceptionRecord;
while( pER )
{
fwrite( pER, 1, sizeof(EXCEPTION_RECORD), fp );
pER = pER->ExceptionRecord; 
}
fwrite(lpExceptionInfo->ContextRecord, 1, sizeof(CONTEXT), fp );
fclose(fp);

LONG lResult = lpExceptionInfo -> ExceptionRecord ->ExceptionCode;

DWORD nThreadId =   GetCurrentThreadId();   
DWORD nProcessId=   GetCurrentProcessId();  

CString   CsErrDescr;   
CsErrDescr.Format("Exception:%d  at CMD   0x%.8x<ThreadId:%d>",
lpExceptionInfo->ExceptionRecord->ExceptionCode,
lpExceptionInfo->ExceptionRecord->ExceptionAddress,
nThreadId); 

AfxMessageBox(CsErrDescr);

if(g_ExceptionFilter)
return g_ExceptionFilter(lpExceptionInfo); 

return lResult;
}

BOOL CTest0App::InitInstance()
{
g_ExceptionFilter = SetUnhandledExceptionFilter( MyExceptionFilter);
..........
}


先加这些看看

#4


用F5来运行,如果是只有Release版本出错,则在工程属性Linker,Debugging中,把Generate Debug info设为yes

看程序退出的时候,vc里面有什么错误的提示。

#5


生成符号文件pdb,然后用windbg调试,崩溃时能捕捉到

#6


1 写个测试程序 疯狂的调你的接口函数(各种正确及错误的数据) 你的程序运行在调试模式下
2 用dump

#7


可能要看看你的问题究竟是出在哪方面?是否与硬件有关还是同代码相关。如果同代码相关的话好办。
通过逻辑上的二分法来不断定位你的问题究竟出在哪段代码上。

#8


先设置*异常过滤,
然后再用MiniDump.

#9


如果是debug,那么有很多种方法:
1)可以使用循环日志的方式,输出信息。(这个方法对release也同样有效) 
2)看有没有错误的代码,如0xc0005等信息,如果有有用的信息,则可以使用make文件,查找一下程序的大概位置。
3)可以使用*.pdb,但出现错误的时候,选择继续,断到程序出错的地方。
4)可以使用日志,输出调用堆栈的内容。

#10


请问楼上的大侠,如何使用日志,输出调用堆栈的内容呢?

#11


1)输出日志,主要是把日志存放到一个链表中,这个链表的大小可以设置,当大于最大值的时候,再删除前面的若干条,然后继续使用这个日志。在debug环境下,可以使用vc一个调试参数,输出一些信息,不过需要注意把所有的TRACE()都关闭掉。
2)至于如何输出调用堆栈的内容,网上有现成的代码,可以搜索以下。

#12


C++ Stack Traces
Collecting the call stack in real time
http://www.ddj.com/184405270

#13


非常感谢大家的回音,根据F5运行,居然发现是:
//...

::EnterCriticalSection(&pContext->Lock);

//...

会不定时的出错,在出错时候,我检查了pContext指针是有效的,
EnterCriticalSection和LeaveCriticalSection都是正常的使用.
难道EnterCriticalSection这类的函数在运行太多次后也有可能出错?!
并且这样的函数一出错,如果不使用try捕捉,当发生出错时候,进程直接就结束的. 

#14


这个不一定就是这段代码出现了错误。
可能是因为同步没有做好,而引起的错误。

#15


凤矶写的东西不错

#1




崩溃?

#2


1:写程序日志
2:把程序在debug状态下运行,看出错的时候是否能断点到你出错的地方

#3



LPTOP_LEVEL_EXCEPTION_FILTER g_ExceptionFilter = NULL;
LONG WINAPI MyExceptionFilter (struct _EXCEPTION_POINTERS* lpExceptionInfo)
{
#ifdef   _DEBUG   
DebugBreak();   
#endif   

FILE *fp =fopen("d:\\error.dat","wb");
struct _EXCEPTION_RECORD* pER = lpExceptionInfo->ExceptionRecord;
while( pER )
{
fwrite( pER, 1, sizeof(EXCEPTION_RECORD), fp );
pER = pER->ExceptionRecord; 
}
fwrite(lpExceptionInfo->ContextRecord, 1, sizeof(CONTEXT), fp );
fclose(fp);

LONG lResult = lpExceptionInfo -> ExceptionRecord ->ExceptionCode;

DWORD nThreadId =   GetCurrentThreadId();   
DWORD nProcessId=   GetCurrentProcessId();  

CString   CsErrDescr;   
CsErrDescr.Format("Exception:%d  at CMD   0x%.8x<ThreadId:%d>",
lpExceptionInfo->ExceptionRecord->ExceptionCode,
lpExceptionInfo->ExceptionRecord->ExceptionAddress,
nThreadId); 

AfxMessageBox(CsErrDescr);

if(g_ExceptionFilter)
return g_ExceptionFilter(lpExceptionInfo); 

return lResult;
}

BOOL CTest0App::InitInstance()
{
g_ExceptionFilter = SetUnhandledExceptionFilter( MyExceptionFilter);
..........
}


先加这些看看

#4


用F5来运行,如果是只有Release版本出错,则在工程属性Linker,Debugging中,把Generate Debug info设为yes

看程序退出的时候,vc里面有什么错误的提示。

#5


生成符号文件pdb,然后用windbg调试,崩溃时能捕捉到

#6


1 写个测试程序 疯狂的调你的接口函数(各种正确及错误的数据) 你的程序运行在调试模式下
2 用dump

#7


可能要看看你的问题究竟是出在哪方面?是否与硬件有关还是同代码相关。如果同代码相关的话好办。
通过逻辑上的二分法来不断定位你的问题究竟出在哪段代码上。

#8


先设置*异常过滤,
然后再用MiniDump.

#9


如果是debug,那么有很多种方法:
1)可以使用循环日志的方式,输出信息。(这个方法对release也同样有效) 
2)看有没有错误的代码,如0xc0005等信息,如果有有用的信息,则可以使用make文件,查找一下程序的大概位置。
3)可以使用*.pdb,但出现错误的时候,选择继续,断到程序出错的地方。
4)可以使用日志,输出调用堆栈的内容。

#10


请问楼上的大侠,如何使用日志,输出调用堆栈的内容呢?

#11


1)输出日志,主要是把日志存放到一个链表中,这个链表的大小可以设置,当大于最大值的时候,再删除前面的若干条,然后继续使用这个日志。在debug环境下,可以使用vc一个调试参数,输出一些信息,不过需要注意把所有的TRACE()都关闭掉。
2)至于如何输出调用堆栈的内容,网上有现成的代码,可以搜索以下。

#12


C++ Stack Traces
Collecting the call stack in real time
http://www.ddj.com/184405270

#13


非常感谢大家的回音,根据F5运行,居然发现是:
//...

::EnterCriticalSection(&pContext->Lock);

//...

会不定时的出错,在出错时候,我检查了pContext指针是有效的,
EnterCriticalSection和LeaveCriticalSection都是正常的使用.
难道EnterCriticalSection这类的函数在运行太多次后也有可能出错?!
并且这样的函数一出错,如果不使用try捕捉,当发生出错时候,进程直接就结束的. 

#14


这个不一定就是这段代码出现了错误。
可能是因为同步没有做好,而引起的错误。

#15


凤矶写的东西不错