介绍
某个代理服务器在压力测试时发生异常,以下是定位过程
保存dump
因为提早有知道程序会出现异常,所以中间省去了很多步骤,在服务启动时就已经使用windbg attach到了服务进程上,这样一旦程序触发异常windbg立即就会捕获。
dump下载:链接:https://pan.baidu.com/s/1Ntm3MRQnbMqGtLkAushSvg 提取码:nvu1
分析过程
程序异常
在程序运行了15小时之后,程序触发了异常,windbg 上使用 命令 !analyze -v 分析异常原因
1 | Failed calling InternetOpenUrl, GLE=12002 |
查看堆栈
从堆栈信息中可以看到,在mp::MPSocket::create_ssl 中new了对象,然后new.cpp@62 抛出了一个异常
1 | void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc) |
查看内存信息
使用工具processxp 查看对应服务的内存状态,虚拟内存、提交内存 都是很低的,不太可能会出现内存申请失败。
进一步确认原因
1 | EXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff) |
google 搜索 “e06d7363 (C++ EH exception)”, 查看链接:https://blogs.msdn.microsoft.com/oldnewthing/20100730-00/?p=13273
按照它的步骤进一步确认C++ 异常原因:
1 | 0:008> dd 746dc7fc l4 ---> 是小写的“L" |
发现的确是 “bad_alloc@std” 导致的异常。
仔细观察物理机器的状态,发现其中一个redis服务吃了大概2G多的内存,会不会是这个原因导致服务进程在申请pagefile时失败呢? 杀掉异常进程继续观察。
总结
长时间观察程序正常。本文的目的主要是介绍如何解码c++异常的具体原因。
附其他操作
1 | 026ffa58 7470da6a 026ffa68 746dc7fc 746dd1cc msvcr120!_CxxThrowException+0x5b (FPO: [Non-Fpo]) (CONV: stdcall) [f:\dd\vctools\crt\crtw32\eh\throw.cpp @ 152] |
1 | __CxxThrowException( |
746dc7fc 其实就是_ThrowInfo 结构体的指针信息,通过watch查看
1 | typedef const struct _s__ThrowInfo |
结构体中重要的成员是_CatchableTypeArray。它包含了程序运行时抛出对象的类新信息(RTTI).
如果你的程序运行时抛出一个my_exception类型的对象,那么抛出的数据参数pCatchableTypeArray包含了两个重要子数据信息。一个是typeid(my_exception),另外一个是typeid(std::exception)。
所以通过watch查看:
1 | (ThrowInfo*)0x746dc7fc 0x746dc7fc struct _s_ThrowInfo * |
1 | dd 0x746dc80c |
1 | watch 中查看(_s_CatchableType*)0x746dd1ac |