今天在写一个文件合并小工具, 因为程序较小, 编译成Release版带调试符号, 直接运行的.
后来改了点东西, 运行时突然报错.
我以前已经运行过(WinDbg -I), 在本机已经将WinDbg作为默认调试器,
当报错时, 被WinDbg接住了~
!analyze -v, 我没有看到源码崩溃行指示, 和我上次专门做的实验表现不一样.
现在要加载工具的符号, 使 !analyze -v 可以看到源码崩溃行才行~
如果是调试远程应用程序, 要运行
.reload /f /user
但是那是在内核层运行的命令, 现在被WinDbg接住时, 上下文是在崩溃的应用层程序
0:000> .reload /f /user
.reload /user is kernel-only
需要运行 .reload /f, 重新加载应用层的模块
在运行此命令之前, 需要设置符号路径, 源路径, 映像路径.
因为我根本没想到应用程序会崩溃~~, 开始就没设置WinDbg参数到此应用程序.
0:000> .reload /f
Reloading current modules
.......
这回工具程序的符号加载上了.
开始分析崩溃的上下文
0:000> !analyze -v
*******************************************************************************
* *
* Exception Analysis *
* *
*******************************************************************************
FAULTING_IP:
MSVCR90!_woutput_l+94c
720f6b1d 66833800 cmp word ptr [eax],0
EXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 720f6b1d (MSVCR90!_woutput_l+0x0000094c)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000000
Parameter[1]: 27fd9d7b
Attempt to read from address 27fd9d7b
FAULTING_THREAD: 000020b4
DEFAULT_BUCKET_ID: INVALID_POINTER_READ
PROCESS_NAME: prjMergeFile.exe
ERROR_CODE: (NTSTATUS) 0xc0000005 - 0x%08lx
EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - 0x%08lx
EXCEPTION_PARAMETER1: 00000000
EXCEPTION_PARAMETER2: 27fd9d7b
READ_ADDRESS: 27fd9d7b
FOLLOWUP_IP:
MSVCR90!_woutput_l+94c
720f6b1d 66833800 cmp word ptr [eax],0
MOD_LIST: <ANALYSIS/>
NTGLOBALFLAG: 0
APPLICATION_VERIFIER_FLAGS: 0
CONTEXT: 002fdd34 -- (.cxr 0x2fdd34)
eax=27fd9d7b ebx=27fd9d7b ecx=00000007 edx=00000073 esi=00eb3530 edi=7ffffffe
eip=720f6b1d esp=002fe198 ebp=002fe618 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
MSVCR90!_woutput_l+0x94c:
720f6b1d 66833800 cmp word ptr [eax],0 ds:002b:27fd9d7b=????
Resetting default scope
LAST_CONTROL_TRANSFER: from 720d6215 to 720f6b1d
PRIMARY_PROBLEM_CLASS: INVALID_POINTER_READ
BUGCHECK_STR: APPLICATION_FAULT_INVALID_POINTER_READ
STACK_TEXT:
002fe618 720d6215 721373c8 00eb34e8 00000000 MSVCR90!_woutput_l+0x94c
002fe65c 00eb1735 00eb34e8 27fd9d7b 00000000 MSVCR90!wprintf+0x73
002ff6ac 00eb1567 00000038 0000003c 00000038 prjMergeFile!AppendSrcFileToDstFile+0x195 [d:\lsworkdir\debugtools\prjmergefile\prjmergefile.cpp @ 261]
002ff6d0 00eb122f 006a8fd0 006a9020 9041ec72 prjMergeFile!AppendSrcFileToDstFile+0x107 [d:\lsworkdir\debugtools\prjmergefile\prjmergefile.cpp @ 208]
002ff760 00eb1068 006a3f4e 00eb4034 00000000 prjMergeFile!mergeFile+0x17f [d:\lsworkdir\debugtools\prjmergefile\prjmergefile.cpp @ 82]
002ff774 00eb18f8 00000002 006a3f20 006a9ef0 prjMergeFile!wmain+0x68 [d:\lsworkdir\debugtools\prjmergefile\prjmergefile.cpp @ 41]
002ff7b8 76ad33aa 7efde000 002ff804 77589ef2 prjMergeFile!__tmainCRTStartup+0x10f [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 583]
002ff7c4 77589ef2 7efde000 7337b422 00000000 kernel32!BaseThreadInitThunk+0xe
002ff804 77589ec5 00eb1a40 7efde000 00000000 ntdll!__RtlUserThreadStart+0x70
002ff81c 00000000 00eb1a40 7efde000 00000000 ntdll!_RtlUserThreadStart+0x1b
SYMBOL_STACK_INDEX: 0
SYMBOL_NAME: msvcr90!_woutput_l+94c
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: MSVCR90
IMAGE_NAME: MSVCR90.dll
DEBUG_FLR_IMAGE_TIMESTAMP: 4dace5b9
STACK_COMMAND: .cxr 0x2fdd34 ; kb
FAILURE_BUCKET_ID: INVALID_POINTER_READ_c0000005_MSVCR90.dll!_woutput_l
BUCKET_ID: APPLICATION_FAULT_INVALID_POINTER_READ_msvcr90!_woutput_l+94c
Followup: MachineOwner
---------
对照源码, 看到了 WinDbg指示 261行有错误.
if (llRdAll > 0)
{
_tprintf(L"(llRdAll(%ld) == llWrAll(%ld)) is %s, \r\n",
llRdAll,
llWrAll,
(llRdAll == llWrAll) ? L"TRUE" : L"FALSE");
}
看了被指示的代码, 就明白了~
应该是_tprintf打印的格式化串中, LONGLONG的打印格式不是%ld ~~, 查下
有人和我遇到了一样的问题, 很快就查到了
<<How to printf long long>>http://stackoverflow.com/questions/6400180/how-to-printf-long-long
修改后的代码
if (llRdAll > 0)
{
_tprintf(L"(llRdAll(%I64d) == llWrAll(%I64d)) is %s\r\n",
llRdAll,
llWrAll,
(llRdAll == llWrAll) ? L"TRUE" : L"FALSE");
}
%I64d格式化 LONGLONG 或 ULONGLONG, 我以前也是经常用的, 怎么今天掉链子~~
用WinDbg直接快速定位解决程序崩溃, 感觉很好~