有个程序总是在windows 2003 server 异常退出. 并且,  查看调用栈也肯奇怪, 应该是很正常的调用. 怀疑是堆溢出.

开启heap trace :

C:\Program Files\Debugging Tools for Windows (x86)>gflags -i app.exe +ust +hpa

发现在Font.ToLogFont函数遇到: {"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."}

如下图:

用Windbg打开exe后发现:

(12e8.13e4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=07362e9c ebx=00000001 ecx=00000003 edx=4dd77680 esi=07362f4c edi=09b03000
eip=4ddccc1c esp=0012e894 ebp=0012e8e8 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
gdiplus!GpFont::GetLogFontW+0x12d:
4ddccc1c f3a5 rep movs dword ptr es:[edi],dword ptr [esi]

汇编代码:

4ddccc11 8b7004          mov     esi,dword ptr [eax+4]
4ddccc14 6a10 push 10h
4ddccc16 03f0 add esi,eax
4ddccc18 83c71c add edi,1Ch
4ddccc1b 59 pop ecx
4ddccc1c f3a5 rep movs dword ptr es:[edi],dword ptr [esi]

重新运行程序,在4ddccc1b处打断点,

0:007> bp 4ddccc1b
0:007> g
Breakpoint 0 hit
eax=07362e9c ebx=00000001 ecx=5d5be675 edx=4dd77680 esi=07362f18 edi=080b2fdc
eip=4ddccc1b esp=0012e890 ebp=0012e8e8 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
gdiplus!GpFont::GetLogFontW+0x12c:
4ddccc1b 59 pop ecx

查看edi所在堆还有多少可写空间,

0:000> !heap -p -a edi
address 080b2fdc found in
_DPH_HEAP_ROOT @ 151000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
9bf6380: 80b2fc0 3c - 80b2000 2000
7c83d7f0 ntdll!RtlAllocateHeap+0x00000e9f
776bcfde ole32!CRetailMalloc_Alloc+0x00000016
776bcf4b ole32!CoTaskMemAlloc+0x00000013
79ac4920 mscorlib_ni+0x00244920
79aca07b mscorlib_ni+0x0024a07b
79ab516a mscorlib_ni+0x0023516a
7b1effc4 System_Drawing_ni+0x0004ffc4
7b1e46c0 System_Drawing_ni+0x000446c0
7b1e452d System_Drawing_ni+0x0004452d 0:000> ? 80b2fc0+ 0x3c - edi
Evaluate expression: 32 = 00000020

剩余32字节.

而ecx指示需要写入0x10 * 4=0x40字节:

0:000> p
eax=07362e9c ebx=00000001 ecx=00000010 edx=4dd77680 esi=07362f18 edi=080b2fdc
eip=4ddccc1c esp=0012e894 ebp=0012e8e8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
gdiplus!GpFont::GetLogFontW+0x12d:
4ddccc1c f3a5 rep movs dword ptr es:[edi],dword ptr [esi]

显然不够用, 执行后抛出AV:

(6d8.1310): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=07362e9c ebx=00000001 ecx=00000007 edx=4dd77680 esi=07362f3c edi=080b3000
eip=4ddccc1c esp=0012e894 ebp=0012e8e8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202
gdiplus!GpFont::GetLogFontW+0x12d:
4ddccc1c f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
0:000> ?(3c - 20)/4
Evaluate expression: 7 =

ecx 还剩7个DWORD写不下.

原因是什么??

LOGFONT在C#中定义是:

 [StructLayout(LayoutKind.Sequential)]
private class LOGFONT
{
public int lfHeight = ;
public int lfWidth = ;
public int lfEscapement = ;
public int lfOrientation = ;
public int lfWeight = ;
public byte lfItalic = ;
public byte lfUnderline = ;
public byte lfStrikeOut = ;
public byte lfCharSet = ;
public byte lfOutPrecision = ;
public byte lfClipPrecision = ;
public byte lfQuality = ;
public byte lfPitchAndFamily = ;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32) ]
public string lfFaceName = "";
}

WinGDI.h定义:

/* Logical Font */
#define LF_FACESIZE 32 typedef struct tagLOGFONTA
{
LONG lfHeight;
LONG lfWidth;
LONG lfEscapement;
LONG lfOrientation;
LONG lfWeight;
BYTE lfItalic;
BYTE lfUnderline;
BYTE lfStrikeOut;
BYTE lfCharSet;
BYTE lfOutPrecision;
BYTE lfClipPrecision;
BYTE lfQuality;
BYTE lfPitchAndFamily;
CHAR lfFaceName[LF_FACESIZE];
} LOGFONTA, *PLOGFONTA, NEAR *NPLOGFONTA, FAR *LPLOGFONTA;

看上去没有任何问题啊!!

但是 gdiplus并没有按照CHAR来处理传入进去的字符串, 相反, 是按照WCHAR来处理的.

WinGDI.h对于宽字符的LOGFONT定义是:

typedef struct tagLOGFONTW
{
LONG lfHeight;
LONG lfWidth;
LONG lfEscapement;
LONG lfOrientation;
LONG lfWeight;
BYTE lfItalic;
BYTE lfUnderline;
BYTE lfStrikeOut;
BYTE lfCharSet;
BYTE lfOutPrecision;
BYTE lfClipPrecision;
BYTE lfQuality;
BYTE lfPitchAndFamily;
WCHAR lfFaceName[LF_FACESIZE];
} LOGFONTW, *PLOGFONTW, NEAR *NPLOGFONTW, FAR *LPLOGFONTW;

因此是C#中的定义lfFaceName长度只有一半!

解决方法就是C#中定义 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]

WinDbg 解决Font.ToLogFont AccessViolationExcetion的更多相关文章

  1. WinDbg解决BHO不加载

    昨天zhengwei同学说他机器上的一个BHO不能正常加载,我把BHO的代码拿过来,在我的两台机器上都验证了一下,一台是Win7+IE8的环境,一台是XP+IE7的环境,都能正常加载.zhengwei ...

  2. Windbg解决系统蓝屏

    win10企业版连续两天遭遇系统蓝屏, 今天就各种检查,准备好好地研究一下这个问题,以下是整个过程: 首先,找到系统蓝屏时的错误日志: [计算机] --> [管理] --> [系统工具] ...

  3. WINDBG解决cpu占高的问题

    https://blog.csdn.net/yenange/article/details/62886988 https://blog.csdn.net/zhushentian/article/det ...

  4. 再记一次w3wp占用CPU过高的解决过程(Dictionary和线程安全)

    在此之前项目有发生过两次类似的状况,都得以解决,但最近又会发现偶尔CPU会跑满,虽然之前使用过WinDbg解决过两次问题但人的记忆是不可靠的,今天处理同样问题的时候还是遇到了一些障碍,这一次希望可以记 ...

  5. 记一次w3wp占用CPU过高的解决过程(Dictionary和线程安全)

    项目上线以来一直存在一个比较揪心的问题,和一个没有信心处理的BUG,那就是在应用程序启动时有可能会导致cpu跑满99%或持续在一个值如50%左右,这样一来对服务器的压力是非常大的,经常出现服务器无法远 ...

  6. 改变 font Awesome、Ionic 图标属性

    可使用 -webkit-text-stroke属性. 例如: -webkit-text-stroke:1px red 使用color属性,可改变 图标颜色: 例如: color: red: 使用fon ...

  7. Windbg(2)

    摘抄于:http://www.cnblogs.com/awpatp/category/228209.html Debug相关的一些小技巧 摘要: 1. 如何Debug一个进程的子进程? 答: 使用Wi ...

  8. windbg(1)

    1.http://www.cnblogs.com/huangyong9527/category/384128.html 2.http://www.cnblogs.com/pugang/category ...

  9. Goodbye2014,Hello2015

    正如我在研发会议上说的,总结是为了更好的计划:而计划,则是让你做事有目标,有方向:有了目标和方向,你才能真正把事情做成! 总的来说2014年可以归纳为下图: 2014年总结 一年的活动,基本可以归纳为 ...

随机推荐

  1. ant design pro (九)引入外部模块

    一.概述 原文地址:https://pro.ant.design/docs/import-cn 除了 antd 组件以及脚手架内置的业务组件,有时我们还需要引入其他外部模块,这里以引入富文本组件 re ...

  2. [原]理解HTTP之Content-Type

    http://homeway.me/2015/07/19/understand-http-about-content-type/ 0x01.About 查看Restful API 报头插件:utm_s ...

  3. Tags Used In OpenERP 7.0

    In OpenERP 7.0. the form view of each object has been redesigned so that the object the user is work ...

  4. js获取时间戳的三种方式

      js获取时间戳的三种方式 CreateTime--2018年5月23日08:44:10 Author:Marydon // 方式一:推荐使用 var timestamp=new Date().ge ...

  5. chrome 此网页正试图从未经验证的来源加载脚本

      chrome 此网页正试图从未经验证的来源加载脚本 CreateTime--2018年5月25日08点02分 Author:Marydon 1.情景还原 以我的网站为例,https://www.c ...

  6. eclipse debug 错误 之 processWorkerExit

    eclipe 在debug模式下,有时候老是跳转到 ThreadPoolExecutor 之 processWorkerExit方法,很是让人恼火,是 因为在 java.util.concurrent ...

  7. mybatis开始

    1,安装mysql. 2,安装nvicat. 云盘上已经上传,另外也可看这里: http://www.cnblogs.com/alsf/diary/2017/12/26/8117263.html 3, ...

  8. Python操作redis系列以 哈希(Hash)命令详解(四)

    # -*- coding: utf-8 -*- import redis #这个redis不能用,请根据自己的需要修改 r =redis.Redis(host=") 1. Hset 命令用于 ...

  9. 让 Node.js 支持 ES6 的语法

    为了让 Node.js 支持 ES6 的语法, 需要使用 Babel. 安装 es-checker 在使用 Babel 之前 , 我们先检测一下当前 node 对 es6 的支持情况. 在命令行下执行 ...

  10. unity, animator stateMachine立即触发状态转换

    例如按下键jump按钮人物执行跳起动作,同时动画状态由idle转换为jump,同时打开Game窗口和Animator窗口对比观察,发现人物跳起时动画状态并没有同步发生转换,而是有一定延迟,导致人物动画 ...