有个程序总是在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. 【Linux】df命令

    用途 df命令主要用于检查Linux服务器的文件系统的磁盘空间占用情况 全称 df的全称为:Disk Free 参数 -a :全部文件系统列表 -h :方便阅读显示 -H :等于"-h&qu ...

  2. android 使用AChartEngine 饼图的实现

    1.AChartEngine 简介 AChartEngine是为Android应用而设计的绘图工具库.可用于绘制多种图表,我使用的是achartengine-1.1.0.jar.ChartEngine ...

  3. Android WiFi热点7.1以上版本适配

    代码地址如下:http://www.demodashi.com/demo/13907.html 一.准备工作 开发环境:  jdk1.8  AS(3.0.1) 运行环境:  华为V10(Android ...

  4. Ubuntu分区方案归总

     更新时间:2010-8-26   一.各文件及文件夹的定义 /bin:bin是binary(二进制)的缩写.存放必要的命令  存放增加的用户程序. /bin分区,存放标准系统实用程序. /boot: ...

  5. Linux命令-帮助命令:help

    which cd 查找cd命令的位置 which umask 查找umask命令的位置 Shell就是命令解释器,就是当你敲了一个命令,谁来把这个命令传递给内核,内核运行结束后返回一个结果,是谁把这个 ...

  6. 引用、数组引用与指针引用、内联函数inline、四种类型转换运算符

    一.引用 (1).引用是给一个变量起别名 定义引用的一般格式:类型  &引用名 = 变量名: 例如:int a=1;  int  &b=a;// b是a的别名,因此a和b是同一个单元 ...

  7. UML建模学习3:UML基本构造块之关系

    今天我们来看UML基本构造块的还有一个要素--关系. UML中有表示基本图示符号之间的关系,它们是:依赖(dependency).泛化(generalization,也有的称继承).实 现(reali ...

  8. SEH, SAFESEH相关

    SEH, SAFESEH相关 1,触发seh异常让目标程序Read/Write无效地址,如果和栈底相邻的内存只读,尝试覆盖超出栈底 2,如何找到(显示)要覆盖的SEHod语法:dd fs:[0]sof ...

  9. TCP/IP 端口大全

    1 tcpmux TCP 端口服务多路复用 5 rje 远程作业入口 7 echo Echo 服务 9 discard 用于连接测试的空服务 11 systat 用于列举连接了的端口的系统状态 13 ...

  10. Informix 語法

    1.修改表名稱 RENAME TABLE old_table_name TO new_table_name; 2.分頁 select  SKIP 0 FIRST 1 * from tablename ...