诚心求助一个关系到调试的问题

stevecrisewu 2005-08-26 11:13:47
我的程序在经过长时间的测试以后,没有发现问题
但是拿到客户那里去以后,实际测试过程中发现程序会自动推出,没有弹出任何提示,有时候会弹出异常(我用SetUnhandledExceptionFilter来捕获异常),这种情况发生了几次,但是大部分时间里不发生。
捕获到异常时候,对话框显示的都是Access Violation错误。

1.一般是什么原因导致的
2.因为不能现场调试,用什么手段去调试比较好
3.浮点0除以浮点0会引发什么问题吗?

期待你的建议,谢谢。
...全文
340 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
windcsn 2005-08-26
  • 打赏
  • 举报
回复
c=-1.#IND000
DentistryDoctor 2005-08-26
  • 打赏
  • 举报
回复
float a,b,c;
a=0;
b=0;
c=a/b;

???被编译器优化掉了。
a=0,b=0,但在内容中也不一定就是0.00000000000000
stevecrisewu 2005-08-26
  • 打赏
  • 举报
回复
float a,b,c;
a=0;
b=0;
c=a/b;

我的这段程序,10ms就运行一次,怎么都没有出错
我原先以为也是浮点错误,但是,却不是这样子,根本不出错。

所以我才问这个问题

谢谢大家
DentistryDoctor 2005-08-26
  • 打赏
  • 举报
回复
浮点0除以浮点0会引发什么问题吗?
引发异常
FLT_DIVIDE_BY_ZERO
快乐鹦鹉 2005-08-26
  • 打赏
  • 举报
回复
我的程序在经过长时间的测试以后,没有发现问题
==测试不全面。
增加日志。
0/0会有异常的
DentistryDoctor 2005-08-26
  • 打赏
  • 举报
回复
有了出错信息和调用堆栈,就可以很好的定位错误了。
在Release版本中,得到的调用堆栈中是0001:001684b4的形式,需要结合.map文件来定位错误。
DentistryDoctor 2005-08-26
  • 打赏
  • 举报
回复
//======================================================================
// Given an exception code, returns a pointer to a static string with a
// description of the exception
//======================================================================
LPTSTR GetExceptionString( DWORD dwCode )
{
#define EXCEPTION( x ) case EXCEPTION_##x: return _T(#x);

switch ( dwCode )
{
EXCEPTION( ACCESS_VIOLATION )
EXCEPTION( DATATYPE_MISALIGNMENT )
EXCEPTION( BREAKPOINT )
EXCEPTION( SINGLE_STEP )
EXCEPTION( ARRAY_BOUNDS_EXCEEDED )
EXCEPTION( FLT_DENORMAL_OPERAND )
EXCEPTION( FLT_DIVIDE_BY_ZERO )
EXCEPTION( FLT_INEXACT_RESULT )
EXCEPTION( FLT_INVALID_OPERATION )
EXCEPTION( FLT_OVERFLOW )
EXCEPTION( FLT_STACK_CHECK )
EXCEPTION( FLT_UNDERFLOW )
EXCEPTION( INT_DIVIDE_BY_ZERO )
EXCEPTION( INT_OVERFLOW )
EXCEPTION( PRIV_INSTRUCTION )
EXCEPTION( IN_PAGE_ERROR )
EXCEPTION( ILLEGAL_INSTRUCTION )
EXCEPTION( NONCONTINUABLE_EXCEPTION )
EXCEPTION( STACK_OVERFLOW )
EXCEPTION( INVALID_DISPOSITION )
EXCEPTION( GUARD_PAGE )
EXCEPTION( INVALID_HANDLE )
}

// If not one of the "known" exceptions, try to get the string
// from NTDLL.DLL's message table.

static TCHAR szBuffer[512] = { 0 };

FormatMessage( FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
GetModuleHandle( _T("NTDLL.DLL") ),
dwCode, 0, szBuffer, sizeof( szBuffer ), 0 );

return szBuffer;
}

DentistryDoctor 2005-08-26
  • 打赏
  • 举报
回复
BOOL GetLogicalAddress(
PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD& offset )
{
MEMORY_BASIC_INFORMATION mbi;

if ( !VirtualQuery( addr, &mbi, sizeof(mbi) ) )
return FALSE;

DWORD hMod = (DWORD)mbi.AllocationBase;

if ( !GetModuleFileName( (HMODULE)hMod, szModule, len ) )
return FALSE;

// Point to the DOS header in memory
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;

// From the DOS header, find the NT (PE) header
PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + pDosHdr->e_lfanew);
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION( pNtHdr );

DWORD rva = (DWORD)addr - hMod; // RVA is offset from module load address

// Iterate through the section table, looking for the one that encompasses
// the linear address.
for ( unsigned i = 0;
i < pNtHdr->FileHeader.NumberOfSections;
i++, pSection++ )
{
DWORD sectionStart = pSection->VirtualAddress;
DWORD sectionEnd = sectionStart
+ max(pSection->SizeOfRawData, pSection->Misc.VirtualSize);

// Is the address in this section???
if ( (rva >= sectionStart) && (rva <= sectionEnd) )
{
// Yes, address is in the section. Calculate section and offset,
// and store in the "section" & "offset" params, which were
// passed by reference.
section = i+1;
offset = rva - sectionStart;
return TRUE;
}
}
return FALSE; // Should never get here!
}

//============================================================
// Walks the stack, and writes the results to the report file
//============================================================
void WriteStackDetails(
PCONTEXT pContext,
bool bWriteVariables ) // true if local/params should be output
{
bWriteVariables;
_tprintf( _T("\r\nCall stack:\r\n") );

_tprintf( _T("Address Frame Function SourceFile\r\n") );

DWORD dwMachineType = 0;
// Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag

STACKFRAME sf;
memset( &sf, 0, sizeof(sf) );

#ifdef _M_IX86
// Initialize the STACKFRAME structure for the first call. This is only
// necessary for Intel CPUs, and isn't mentioned in the documentation.
sf.AddrPC.Offset = pContext->Eip;
sf.AddrPC.Mode = AddrModeFlat;
sf.AddrStack.Offset = pContext->Esp;
sf.AddrStack.Mode = AddrModeFlat;
sf.AddrFrame.Offset = pContext->Ebp;
sf.AddrFrame.Mode = AddrModeFlat;

dwMachineType = IMAGE_FILE_MACHINE_I386;
#endif

int nLevel=0;
while ( 1 )
{
// Get the next stack frame
if ( ! StackWalk( dwMachineType,
m_hProcess,
GetCurrentThread(),
&sf,
pContext,
0,
SymFunctionTableAccess,
SymGetModuleBase,
0 ) )
break;

if ( 0 == sf.AddrFrame.Offset ) // Basic sanity check to make sure
break; // the frame is OK. Bail if not.

if(nLevel>2)
_tprintf( _T("%08X %08X "), sf.AddrPC.Offset, sf.AddrFrame.Offset );

// Get the name of the function for this stack frame entry
BYTE symbolBuffer[ sizeof(SYMBOL_INFO) + 1024 ];
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;
pSymbol->SizeOfStruct = sizeof(symbolBuffer);
pSymbol->MaxNameLen = 1024;

DWORD64 symDisplacement = 0; // Displacement of the input address,

// relative to the start of the symbol
#ifdef _DEBUG
if ( SymFromAddr(m_hProcess,sf.AddrPC.Offset,&symDisplacement,pSymbol))
{
if(nLevel>2)
_tprintf( _T("%hs+%I64X"), pSymbol->Name, symDisplacement );
}
else // No symbol found. Print out the logical address instead.
#endif
{
TCHAR szModule[MAX_PATH] = _T("");
DWORD section = 0, offset = 0;

GetLogicalAddress( (PVOID)sf.AddrPC.Offset,
szModule, sizeof(szModule), section, offset );

if(nLevel>2)
_tprintf( _T("%04X:%08X %s"), section, offset, szModule );
}

// Get the source line for this stack frame entry
IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) };
DWORD dwLineDisplacement;
if ( SymGetLineFromAddr( m_hProcess, sf.AddrPC.Offset,
&dwLineDisplacement, &lineInfo ) )
{
if(nLevel>2)
_tprintf(_T(" %s line %u"),lineInfo.FileName,lineInfo.LineNumber);
}
if(nLevel>2)
_tprintf( _T("\r\n") );
++nLevel;
}

}
DentistryDoctor 2005-08-26
  • 打赏
  • 举报
回复
LONG WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo )
{
PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;

// First print information about the type of fault
_tprintf( _T("Exception code: %08X %s\r\n"),
pExceptionRecord->ExceptionCode,
GetExceptionString(pExceptionRecord->ExceptionCode) );

// Now print information about where the fault occured
TCHAR szFaultingModule[MAX_PATH];
DWORD section, offset;
GetLogicalAddress( pExceptionRecord->ExceptionAddress,
szFaultingModule,
sizeof( szFaultingModule ),
section, offset );

_tprintf( _T("Fault address: %08X %02X:%08X %s\r\n"),
pExceptionRecord->ExceptionAddress,
section, offset, szFaultingModule );

PCONTEXT pCtx = pExceptionInfo->ContextRecord;

// Show the registers
#ifdef _M_IX86 // X86 Only!
_tprintf( _T("\r\nRegisters:\r\n") );

_tprintf(_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n")
,pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx,
pCtx->Esi, pCtx->Edi );

_tprintf( _T("CS:EIP:%04X:%08X\r\n"), pCtx->SegCs, pCtx->Eip );
_tprintf( _T("SS:ESP:%04X:%08X EBP:%08X\r\n"),
pCtx->SegSs, pCtx->Esp, pCtx->Ebp );
_tprintf( _T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs );
_tprintf( _T("Flags:%08X\r\n"), pCtx->EFlags );

#endif

SymSetOptions( SYMOPT_DEFERRED_LOADS );

// Initialize DbgHelp
if ( !SymInitialize( GetCurrentProcess(), 0, TRUE ) )
return;

CONTEXT trashableContext = *pCtx;

WriteStackDetails( &trashableContext, false );
}
hamimelon 2005-08-26
  • 打赏
  • 举报
回复
内存访问异常
除数不能为0
DentistryDoctor 2005-08-26
  • 打赏
  • 举报
回复
Access Violation?具体地址?


同时可以在SetUnhandledExceptionFilter,中取得异常的详细信息和调用堆栈。
oyljerry 2005-08-26
  • 打赏
  • 举报
回复
可能内存访问异常
作一些日志记录,来分析问题
pomelowu 2005-08-26
  • 打赏
  • 举报
回复
用SetUnhandledExceptionFilter可以获得详细的异常信息,看看具体是什么原因吧
http://blog.csdn.net/pomelowu/archive/2005/08/02/444254.aspx

除浮点0也会造成除0异常的。
windcsn 2005-08-26
  • 打赏
  • 举报
回复
1.你访问了不可访问的资源,内存被修改等等
2.建议你做运行日志,如果客户运行出错,将他的日志发给你,有助于你发现问题
3.除零异常啊
pomelowu 2005-08-26
  • 打赏
  • 举报
回复
这样就能在InitInstance前注册自己的ExceptionFilter
pomelowu 2005-08-26
  • 打赏
  • 举报
回复
用cod文件吧,比map文件更详细。这样也就无需/mapinfo:lines 开关。另,使用/mapinfo:lines就不能使用增量编译的开关(/incremental)。要使用/mapinfo:lines也可以不用手动填写,Linker选项卡上Map Lines 选项前打勾即可。


最好单独做一个ExceptionHandle的类,把SetUnhandledExceptionFilter放到构造函数中,然后声明一个这个类的全局对象。这样就能在InitInstance注册自己的ExceptionFilter
stevecrisewu 2005-08-26
  • 打赏
  • 举报
回复
为什么SetUnhandledExceptionFilter之后,在有异常发生时候,没有被捕获,现象就是程序自动退出,没有留下任何痕迹就退出?

我是在InitInstance中设置过滤器的
stevecrisewu 2005-08-26
  • 打赏
  • 举报
回复
为什么编译器告诉我ignoring unknown option '/mapinfo:lines'

当我选择了mapfile,将/mapinfo:lines 加到Project Option
sycnick 2005-08-26
  • 打赏
  • 举报
回复
增加日志,修改测试用例
pomelowu 2005-08-26
  • 打赏
  • 举报
回复
Access Violation 一般是非法地址访问造成的,比如NULL指针使用等等。
用SetUnhandledExceptionFilter配合.cod文件定位错误代码(可以写日志方式输出),然后再分析会比较好。

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧