- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
前些天有位朋友找到我,说他的程序跑着跑着就崩溃了,让我看下怎么回事,其实没怎么回事,抓它的 crash dump 就好,具体怎么抓也是被问到的一个高频问题,这里再补一下链接: [.NET程序崩溃了怎么抓 Dump ? 我总结了三种方案] https://www.cnblogs.com/huangxincheng/p/14811953.html ,采用第二种 AEDebug 的形式抓取即可.
如果dump中塞了异常,用 windbg 打开的时候会有一个提示 This dump file has an exception of interest stored in it ,输出如下:
************* Path validation summary **************
Response Time (ms) Location
Deferred SRV*C:\mysymbols*http://msdl.microsoft.com/download/symbols
Symbol search path is: SRV*C:\mysymbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
Windows 7 Version 7601 (Service Pack 1) MP (4 procs) Free x64
Product: Server, suite: Enterprise TerminalServer SingleUserTS
Debug session time: Wed Jun 14 13:34:49.000 2023 (UTC + 8:00)
System Uptime: 0 days 3:28:04.223
Process Uptime: 0 days 0:00:14.000
................................................................
................................................................
......................................................
This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
(9e4.bc4): Stack overflow - code c00000fd (first/second chance not available)
For analysis of this file, run !analyze -v
clr!SlowAllocateString+0x11:
000007fe`f9236451 48c785b0fffffffeffffff mov qword ptr [rbp-50h],0FFFFFFFFFFFFFFFEh ss:00000000`123d5fd0=0000000000000000
从卦中看当前有一个 Stack overflow - code c00000fd 异常,说实话好久都没看到 栈溢出 了,甚是想念,既然说栈溢出了,那就看下异常前是个啥情况,使用 .excr 即可.
0:028> .excr;k
rax=00000000123d6048 rbx=00000000123d5d70 rcx=0000000000000001
rdx=0000000000000001 rsi=0000000000000000 rdi=00000000123d5880
rip=000007fef9236451 rsp=00000000123d5fb0 rbp=00000000123d6020
r8=00000000ffffffff r9=0000000000000000 r10=00000000123d618e
r11=0000000000000000 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000001
iopl=0 nv up ei pl nz na pe nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010200
clr!SlowAllocateString+0x11:
000007fe`f9236451 48c785b0fffffffeffffff mov qword ptr [rbp-50h],0FFFFFFFFFFFFFFFEh ss:00000000`123d5fd0=0000000000000000
*** Stack trace for last set context - .thread/.cxr resets it
# Child-SP RetAddr Call Site
00 00000000`123d5fb0 000007fe`f920a5bd clr!SlowAllocateString+0x11
01 00000000`123d6050 000007fe`f920a9c7 clr!StringObject::NewString+0x25
02 00000000`123d6080 000007fe`f920a80d clr!Int32ToDecStr+0xdf
03 00000000`123d6320 000007fe`9ab3bb72 clr!COMNumber::FormatInt32+0x10d
04 00000000`123d65f0 000007fe`9ab33e04 0x000007fe`9ab3bb72
05 00000000`123d6630 000007fe`9ab3be52 0x000007fe`9ab33e04
06 00000000`123d6720 000007fe`9ab3bd2a 0x000007fe`9ab3be52
07 00000000`123d6790 000007fe`9ab33e35 0x000007fe`9ab3bd2a
08 00000000`123d67f0 000007fe`9ab3be52 0x000007fe`9ab33e35
09 00000000`123d68e0 000007fe`9ab3bd2a 0x000007fe`9ab3be52
...
ff 00000000`123df860 000007fe`9ab3bd2a 0x000007fe`9ab3be52
从卦中看,当前默认的 255 个栈帧全部被打满,看样子是无限死循环了,为了能看到托管部分我们改用 !clrstack 命令.
0:028> !clrstack
OS Thread Id: 0xbc4 (28)
Child SP IP Call Site
00000000123d63b8 000007fef9236451 [HelperMethodFrame_PROTECTOBJ: 00000000123d63b8] System.Number.FormatInt32(Int32, System.String, System.Globalization.NumberFormatInfo)
00000000123d65f0 000007fe9ab3bb72 pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Byte[])
00000000123d6630 000007fe9ab33e04 pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Byte[], Int64, Int64, Boolean)
00000000123d6720 000007fe9ab3be52 pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Int32, Int32)
00000000123d6790 000007fe9ab3bd2a pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Byte[], Boolean)
00000000123d67f0 000007fe9ab33e35 pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Byte[], Int64, Int64, Boolean)
00000000123d68e0 000007fe9ab3be52 pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Int32, Int32)
00000000123d6950 000007fe9ab3bd2a pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Byte[], Boolean)
00000000123d69b0 000007fe9ab33e35 pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Byte[], Int64, Int64, Boolean)
00000000123d6aa0 000007fe9ab3be52 pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Int32, Int32)
00000000123d6b10 000007fe9ab3bd2a pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Byte[], Boolean)
00000000123d6b70 000007fe9ab33e35 pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Byte[], Int64, Int64, Boolean)
00000000123d6c60 000007fe9ab3be52 pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Int32, Int32)
00000000123d6cd0 000007fe9ab3bd2a pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Byte[], Boolean)
00000000123d6d30 000007fe9ab33e35 pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Byte[], Int64, Int64, Boolean)
00000000123d6e20 000007fe9ab3be52 pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Int32, Int32)
00000000123d6e90 000007fe9ab3bd2a pdfrender4net_symbol01.pdfrender4net_symbol09.pdfrender4net_symbol00(Byte[], Boolean)
....
000000001244db60 000007fe9ab31f0e xxx.PDFFile.pdfrender4net_symbol00(System.String, System.IO.Stream, Byte[])
000000001244dbc0 000007fe9ab318e5 xxx.xxx.ConvertPDFToImages(System.IO.Stream, Int32, Int32, System.Drawing.Imaging.ImageFormat, Int32)
从卦中信息看,是代码用 ConvertPDFToImages 调用了一个第三方库,在这个库中出现了死递归.
按理说不管外界给了什么参数下去,都不应该用死递归的方式来呈现,所以这类问题可以归于 SDK 的bug,接下来我们的研究方向就是看下这个 SDK 是何方神圣?
[assembly: AssemblyCopyright("© 2008 O2 Solutions")]
[assembly: AssemblyProduct("PDFRender4NET")]
[assembly: AssemblyCompany("O2 Solutions (http://www.o2sol.com/)")]
[assembly: AssemblyTrademark("PDFRender4NET is a trademark of O2 Solutions")]
[assembly: AllowPartiallyTrustedCallers]
[assembly: AssemblyTitle("Print and convert PDF files to images.")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyDescription("Component for rendering pdf files on .NET platform")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyInformationalVersion("2.0.1")]
[assembly: AssemblyKeyName("")]
[assembly: AssemblyDelaySign(false)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("2.0.1.0")]
从卦中看还是 2008 年写的 2.0.1 版本,而官网早已出了 2023 年版本,也就是说 15年都没有更新,也是厉害,截图如下:
到这里就可以给到朋友答案了,让他看下能否把 PDFRender4NET 升级到最新版本,按理说应该就没有问题了.
心细的朋友可能会有一个疑问,既然都栈溢出了,按理说异常码应该是 c0000005 (访问违例),怎么会是 c00000fd 呢?
这是一个非常好的问题,要理解为什么是 c00000fd 而不是 c0000005 ,需要你对栈的布局有一个比较清晰的理解,为了方便讲述,以当前的 w3wp 来绘制一张图.
画完这张图肯定有朋友会提几个反对意见:
1) 线程栈不是 1M 吗? 怎么会是 512k 呢?
这里要说的是 1M 并不是什么公理,可以在 PE 头上随便设定的,截图如下:
2)PAGE_GUARD 不是 1个内存页吗?
很多教科书都是按 1个内存页 讲述的,但这也不是定死的,也可能是多个内存页,比如 2个,5个,要想验证很简单,用 !address -f:Stack 观察下便知.
0:121> !address -f:Stack
BaseAddress EndAddress+1 RegionSize Type State Protect Usage
--------------------------------------------------------------------------------------------------------------------------
0`001f0000 0`00266000 0`00076000 MEM_PRIVATE MEM_RESERVE Stack [~0; 9e4.e30]
0`00266000 0`00268000 0`00002000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE | PAGE_GUARD Stack [~0; 9e4.e30]
0`00268000 0`00270000 0`00008000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE Stack [~0; 9e4.e30]
...
0`15710000 0`15788000 0`00078000 MEM_PRIVATE MEM_RESERVE Stack [~139; 9e4.14ac]
0`15788000 0`1578d000 0`00005000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE | PAGE_GUARD Stack [~139; 9e4.14ac]
0`1578d000 0`15790000 0`00003000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE Stack [~139; 9e4.14ac]
接下来我们聊一下什么是 PAGE_GUARD ,从名字上看就是 哨兵页 ,说白一点就是 Windows 做 栈伸展 的一种系统机制,当 rsp 访问到这个区域时会引发系统的 页中断 进而 COMMIT 更多内存页,新的 Commit 页会被 哨兵 侵占,同时也会让渡 RSP 所占的内存页给程序使用,这是一种良性机制,一旦 哨兵 无法侵占更多新的 COMMIT 页时,也就表示栈空间已经到位了,这时候会将自身的 PAGE_GUARD 标签去掉,表示它的使命已完成,如果此时 RSP 访问到了这个弥留的 哨兵区 ,就会抛出 c00000fd 异常,这种异常只是表示 RSP 进入了 哨兵区 ,不代表 栈空间 真的用完了,所以这就是不抛 c0000005 的真正原因,画个简图如下:
说了这么说,如何去验证呢?非常简单,我们提取出 StackLimit, StackBase, RSP 即可.
0:028> r rsp
rsp=00000000123d5fb0
0:028> !teb
TEB at 000007fffff70000
ExceptionList: 0000000000000000
StackBase: 0000000012450000
StackLimit: 00000000123d1000
0:028> !address -f:Stack
BaseAddress EndAddress+1 RegionSize Type State Protect Usage
--------------------------------------------------------------------------------------------------------------------------
0`123d0000 0`123d1000 0`00001000 MEM_PRIVATE MEM_RESERVE Stack [~28; 9e4.bc4]
0`123d1000 0`12450000 0`0007f000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE Stack [~28; 9e4.bc4]
从卦中看,当前 哨兵区 = StackLimit ~ StackLimit+0x5000 = 00000000123d1000 ~ 00000000123d6000 ,然后看下 rsp=00000000123d5fb0 果然是在这个范围内,在一些低级语言中还可以继续放任 栈溢出 异常,继续让程序跑,当代码跑到图中的 MEM_RESERVE 区时这就是货真价实的 c0000005 访问违例.
这次崩溃事故主要还是第三方的SDK代码不健壮导致的 死递归 拖累程序崩溃,解决办法很简单,升级升级再升级,如果还有问题建议提交官方或者使用其他替代品,如果官方解决问题不活跃,你还敢用吗?
最后此篇关于记一次.NET某旅行社审批系统崩溃分析的文章就讲到这里了,如果你想了解更多关于记一次.NET某旅行社审批系统崩溃分析的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
创建使用.NET框架的asp.net页面时,访问该页面的客户端是否需要在其计算机上安装.NET框架? IE。用户访问www.fakesite.com/default.aspx,如果他们没有安装框架,他
我阅读了很多不同的博客和 StackOverflow 问题,试图找到我的问题的答案,但最后我找不到任何东西,所以我想自己问这个问题。 我正在构建一个应用程序,其中有一个长时间运行的工作线程,它执行一些
已锁定。这个问题及其答案是locked因为这个问题是题外话,但却具有历史意义。目前不接受新的答案或互动。 我一直想知道为什么微软为这样一个伟大的平台选择了一个如此奇怪的、对搜索引擎不友好的名称。他们就
.Net Framework .Net .NET Standard的区别 1、.NET Framework 在未来.NET Framework或许成为过去时,目前还是有很多地方在使用的。这一套
如果有选择的话,您会走哪条路? ASP.NET Webforms + ASP.NET AJAX 或 ASP.NET MVC + JavaScript Framework of your Choice
我有一个 Web 服务,它通过专用连接通过 https 使用第三方 Web 服务,我应用了 ServicePointManager.ServerCertificateValidationCallbac
为什么我应该选择ASP.NET Web Application (.NET Framework)而不是ASP.NET Core Web Application (.NET Framework)? 我在
我在网络上没有找到任何关于包含 .NET Standard、.NET Core 和 .NET Framework 项目的 .NET 解决方案的公认命名约定。 就我而言,我们在 .NET 框架项目中有以
.NET Compact 是 .NET 的完美子集吗? 假设我考虑了屏幕大小和其他限制并避免了 .NET Compact 不支持的类和方法,或者 .NET Compact 是一个不同且不兼容的 GUI
我已经阅读了所有我能找到的关于 connectionManagement 中的 maxconnection 设置的文章:即 http://support.microsoft.com/kb/821268
我现在正在使用asp.net mvc,想知道使用内置的Json或 Json.Net哪个是更好的选择,但我不确定一个人是否比另一个人有优势。 另外,如果我确实选择沿用Json.Net的路线,那么我应该选
在 Visual Studio 中,您至少可以创建三种不同类型的类库: 类库(.NET Framework) 类库(.NET 标准) 类库(.NET Core) 虽然第一个是我们多年来一直使用的,但我
.NET 和 ASP.NET 之间有什么区别?它们有什么关系? 最佳答案 ASP.Net 基于 .Net 框架构建,提供有关 Web 开发的附加功能。 你可以去看看wikipedia article
在安装更高版本(3.0)之前,我需要安装.net框架1.1和2.0吗?或者单独安装 3.0 框架就足够了,并为在早期框架版本上编写的软件提供支持?谢谢 ,丽然 最佳答案 不,您不必安装以前的框架。 我
我正在开发一个项目,人们可以“更新”类别,例如更改类别的名称。我收到以下消息 This is called after clicking update 按钮 with the SQL statemen
.NET 类 System.Net.CookieContainer 线程安全吗? --更新:交 key 答复-- 是否有任何方法可以确保异步请求期间修改的变量(即 HttpWebRequest.Coo
我正在使用 JScript.NET 在我编写的 C# WinForms 应用程序中编写脚本。它工作得很好,但我只是尝试在脚本中放置一些异常处理,但我无法弄清楚如何判断我的 C# 代码抛出了哪种类型的异
我需要你的帮助, 比如我有一个小数类型的变量,我想这样取整。 例如 3.0 = 3 3.1 = 4 3.2 = 4 3.3 = 4 3.4 = 4 3.5 = 4 3.6 = 4 3.7 = 4 3.
我使用过这样的代码:http://msdn.microsoft.com/en-us/library/dw70f090.aspx在 ASP.NET 中工作之前访问数据库(2-3 年前)。我没有意识到我正
自 ConfigurationManager .NET Standard 中不存在,检索正在执行的程序集的应用程序设置的最佳方法是什么,无论是 web.config或 appSettings.{env
我是一名优秀的程序员,十分优秀!