垃圾收集期间崩溃的原因

2024-01-07

一段时间以来,我一直在努力解决 C# 应用程序崩溃的问题,该应用程序也使用相当多的 C++/CLI 模块,这些模块主要是本地库的包装器来访问设备驱动程序。 崩溃并不总是很容易重现,但我能够收集六个崩溃转储,这些崩溃转储表明程序总是在垃圾收集期间因访问冲突而崩溃。这是本机调用堆栈和最后一个事件日志:

0:000> k
ChildEBP RetAddr  
0012d754 79f95a8f mscorwks!WKS::gc_heap::find_first_object+0x62
0012d7dc 79f933bb mscorwks!WKS::gc_heap::mark_through_cards_for_segments+0x493
0012d814 79f92cbf mscorwks!WKS::gc_heap::mark_phase+0xc3
0012d838 79f93245 mscorwks!WKS::gc_heap::gc1+0x62
0012d84c 79f92f5a mscorwks!WKS::gc_heap::garbage_collect+0x253
0012d878 79f94e26 mscorwks!WKS::GCHeap::GarbageCollectGeneration+0x1a9
0012d904 79f926ce mscorwks!WKS::gc_heap::try_allocate_more_space+0x15b
0012d918 79f92769 mscorwks!WKS::gc_heap::allocate_more_space+0x11
0012d938 79e73291 mscorwks!WKS::GCHeap::Alloc+0x3b

0:000> .lastevent
Last event: 7e8.88: Access violation - code c0000005 (first/second chance not available)
  debugger time: Mon Sep 26 11:34:53.646 2011 (UTC + 2:00)

因此,让我首先提出我的问题,并在下面提供更多详细信息。我的问题是:除了托管堆损坏之外,还有其他原因导致垃圾收集期间崩溃吗?

现在详细说明一下,我问这个问题的原因是因为我很难识别破坏托管堆的代码,并且似乎无法找到(据称)被覆盖的内存的模式。

我已经尝试注释所有“危险”C++/CLI 代码(特别是使用固定句柄的部分),但这没有帮助。在试图找到内存中被覆盖的模式时,我查看了崩溃时的反汇编代码:

0:000> u .-a .+a
mscorwks!WKS::gc_heap::find_first_object+0x54:
79f935b9 89450c          mov     dword ptr [ebp+0Ch],eax
79f935bc 8bd0            mov     edx,eax
79f935be 8b02            mov     eax,dword ptr [edx]
79f935c0 83e0fe          and     eax,0FFFFFFFEh
79f935c3 f70000000080    test    dword ptr [eax],80000000h      <<<<CRASH
79f935c9 0f84b1000000    je      mscorwks!WKS::gc_heap::find_first_object+0x73

0:000> r
eax=00000000 ebx=01c81000 ecx=01c80454 edx=01c82fe0 esi=012f0000 edi=000027e1
eip=79f935c3 esp=0012d738 ebp=0012d754 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
mscorwks!WKS::gc_heap::find_first_object+0x62:
79f935c3 f70000000080    test    dword ptr [eax],80000000h ds:0023:00000000=????????

当尝试取消引用空的 EAX 寄存器时,会发生崩溃。现在,我看到 EAX 是从 EDX 寄存器指向的内容加载的,所以我查看了存储在那里的地址:

0:000> dd @edx-10
01c82fd0  06542778 00000000 00000000 01c82494
01c82fe0  00000000 00000000 00000000 00000000
01c82ff0  01b641d0 00000000 00000000 01c82380

编辑:我现在发现我的分析是错误的,缺乏对 x86 寻址模式的理解。

所以我可以看到从地址 01c82fed(存储在 EDX 中的值)开始,接下来的 16 个字节为空。 但是,当查看另一个类似的故障转储时,我看到以下内容:

0:000> dd @edx-10
018defd4  00000000 00000000 00000000 00000000
018defe4  00000000 00000000 018b468c 01742354
018deff4  00e0907f 00000000 00000000 00000000

所以这里 EDX 指向的地址之前的 16 个字节和接下来的 8 个字节为空。同样的情况也发生在我拥有的其他故障转储中,我在这里没有看到任何模式,即似乎某些代码片段只是简单地覆盖了内存的该区域。

回到这个问题,我想知道的是,除了一段不应该覆盖内存的代码之外,是否还有其他对崩溃的解释。或者有任何关于如何进行的建议,我真的迷失在这个地方了..

(固定手柄会导致问题吗?我们有很多这样的手柄,我认为有趣的是,我总是看到 137 - 不多也不少 - 在崩溃时带有 !gchandles 的固定手柄,它是对我来说这是一个奇怪的巧合..)。

EDIT:忘记提及我们正在使用 .Net 框架的 3.5 版本。当后台 GC 处于活动状态时,我在 .Net 4 中看到类似崩溃的报告(某处提到这是 .Net 中的一个错误),但我认为这与此无关,因为 AFAIK 中没有后台 GC .Net 3.5。


不确定这是否有帮助,但通常不要使用析构函数或让 GC 处理非托管内存。请改用 Dispose 模式,并将所有析构函数代码移至终结器:

ref class MyClass
{
  UnsafeObject data;
  MyClass()
  {
    data = CreateUnsafeDataObject();
  }
  !MyClass()  // IDisposable.Dispose()
  {
    DeleteUnsafeDataObject(data);
  }
  ~MyClass()  // Destructor
  {

  }
}

这将在对象上实现 IDisposable 模式。调用 Dispose 来清除非托管数据,在最坏的情况下,您将有更好的机会弄清楚到底发生了什么。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

垃圾收集期间崩溃的原因 的相关文章

  • 起订量要求?违背了目的?

    是否需要虚拟化您想要模拟的所有属性访问器就违背了模拟的目的 我的意思是 如果我必须修改我的对象并虚拟化我想要模拟的每个访问器 我难道不能继承我的类并自己模拟它吗 你的问题非常有效 但如果你仔细想想 没有其他方法可以模拟课程 如果你采用一个接
  • Accept() 是线程安全的吗?

    我目前正在用 C 语言为我正在做的课程编写一个简单的网络服务器 我们的一项要求是实现一个线程池来使用 pthread 处理连接 我知道我将如何粗略地执行此操作 在主线程中调用accept并将文件描述符传递给freee线程 但是我的朋友建议了
  • 为什么 VB.NET 和 C# 中针对值检查 null 存在差异?

    In VB NET http en wikipedia org wiki Visual Basic NET有时候是这样的 Dim x As System Nullable Of Decimal Nothing Dim y As System
  • 键盘加速器在 UWP 应用中停止工作

    我正在尝试将键盘加速器添加到 UWP 应用程序中的 CommandBar 菜单项 当应用程序启动时 这工作正常 但在我第一次打开溢出菜单后 加速器停止工作 这似乎不会发生在主要命令 菜单之外 上 只有溢出菜单内的辅助命令才会发生 此外 单击
  • 无法从 Web api POST 读取正文数据

    我正在尝试从新的 Asp Net Web Api 中的请求中提取一些数据 我有一个像这样的处理程序设置 public class MyTestHandler DelegatingHandler protected override Syst
  • 如何在 Asp.net Gridview 列中添加复选框单击事件

    我在 asp 中有一个 gridview 其中我添加了第一列作为复选框列 现在我想选择此列并获取该行的 id 值 但我不知道该怎么做 这是我的 Aspx 代码
  • 是否有像 gccxml 这样的用于生成包装器的 C 标头解析器工具?

    我需要为一种新的编程语言编写一些 C 标头包装器 并且想要类似 gccxml 的东西 但不完全依赖 gcc 以及它在 Windows 系统上带来的问题 只需要读C而不是C 只要有完整的文档记录 任何格式的输出都可以 Linux Solari
  • 如何使用 wpf webbrowser 将数据发布到 Web 服务器

    我想从数据库获取数据并使用它来让用户登录到网站 我有一个包含 Web 浏览器控件的 wpf 页面 我有这样的代码 用于将用户登录到用 php 编写的网站
  • 默认值 C# 类 [重复]

    这个问题在这里已经有答案了 我在控制器中有一个函数 并且我收到表单的信息 我有这个代码 public Actionresult functionOne string a string b string c foo 我尝试将其转换为类似的类
  • 操纵 setter 以避免 null

    通常我们有 public string code get set 如果最终有人将代码设置为 null 我需要避免空引用异常 我尝试这个想法 有什么帮助吗 public string code get set if code null cod
  • 防止GDB中的PLT(过程链接表)断点

    在最新版本的 GDB 中 在库函数调用上设置断点会导致多个实际断点 调用过程链接表 PLT 实际的函数调用 这意味着当调用库函数时 我们每次都会经历两次中断 在以前的 GDB 版本中 只会创建 2 因此您只能得到一次中断 那么问题来了 是否
  • 在简单注入器中注册具有多个构造函数和字符串依赖项的类型

    我正在尝试弄清楚如何使用 Simple Injector 我在项目中使用了它 注册简单服务及其组件没有任何问题 但是 当组件具有两个以上实现接口的构造函数时 我想使用依赖注入器 public DAL IDAL private Logger
  • 允许使用什么类型的内容作为 C 预处理器宏的参数?

    老实说 我很了解 C 编程语言的语法 但对 C 预处理器的语法几乎一无所知 尽管我有时在编程实践中使用它 所以问题来了 假设我们有一个简单的宏 它扩展为空 define macro param 可以放入宏调用构造中的语法有哪些限制 调用宏时
  • 不兼容的类型 - 是因为数组已经是指针吗?

    在下面的代码中 我创建一个基于书籍结构的对象 并让它保存多个 书籍 我设置的是一个数组 即定义 启动的对象 然而 每当我去测试我对指针的了解 实践有帮助 并尝试创建一个指向创建的对象的指针时 它都会给我错误 C Users Justin D
  • 使用(linq to sql)更新错误

    我有两个表 通过外键 CarrierID 绑定 Carrier CarrierID CarrierName CarrierID 1 CarrierName DHL CarrierID 2 CarrierName Fedex Vendor V
  • 使用 foreach 循环和 XmlNodeList C# 将新节点附加到节点列表

    目前我处理的是这样的XML类型 XML FILE http 20drive google com open id 0By5BxgNi9eGcRldxcEZNU0FDTzQ 参考XML文件 我想检查一个节点 如果找不到该节点 我必须将该节点附
  • 如何将对象转换为传递给函数的类型?

    这不会编译 但我想做的只是将对象转换为传递给函数的 t public void My Func Object input Type t t object ab TypeDescriptor GetConverter t ConvertFro
  • g++ C++0x 枚举类编译器警告

    我一直在将可怕的 C 类型安全伪枚举重构为新的 C 0x 类型安全枚举 因为它们是way更具可读性 不管怎样 我在导出的类中使用它们 所以我明确地将它们标记为导出 enum class attribute visibility defaul
  • 无法使 Polly 超时策略覆盖 HttpClient 默认超时

    我正在使用 Polly 重试策略 并且正如预期的那样 在重试过程中HttpClient达到 100 秒超时 我尝试了几种不同的方法来合并 Polly 超时策略 将超时移至每次重试而不是总计 但 100 秒超时仍然会触发 我读过大约 5 个
  • FindAsync 很慢,但是延迟加载很快

    在我的代码中 我曾经使用加载相关实体await FindAsync 希望我能更好地遵守 C 异步指南 var activeTemplate await exec DbContext FormTemplates FindAsync exec

随机推荐

  • 在 MATLAB 中查找变量的小数位数

    给定变量 x 12 3442 我想知道变量的小数位数 在这种情况下 结果将是 4 如何在不反复试验的情况下做到这一点 这是一个紧凑的方法 y x 10 1 20 find y round y 1 假设x是您的数字 20 是小数点后的最大位数
  • 在java中将数组的字符串表示形式转换回int数组

    刚刚开始使用 Java 编程 如果我有一个存储在 txt 文件中的数组 如下所示 10 22 30 55 10 20 19 如何将其转换回正常的 int 数组以在代码中使用 我需要能够将其简单地存储在这样的 txt 文件中 以便我可以手动对
  • 如何在 Windows 上安装 python-levenshtein?

    经过几天的搜索 我准备放弃寻找 Python 2 7 Windows 64 位 的预编译二进制文件Python Levenshtein 库 http pypi python org pypi python Levenshtein 所以不是我
  • Java 中的 getter/setter

    我是 Java 新手 但有一些使用 ActionScript 3 的 OOP 经验 因此我尝试依靠我所知道的内容进行迁移 在 ActionScript 3 中 您可以使用 get 和 set 关键字创建 getter 和 setter 这意
  • 相机控件在 iOS 7 上不可见

    我使用图像选择器控制器来调用设备相机 下面列出的代码在 iOS 7 下工作正常 但是当我在 iOS 7 上使用相同的代码启动相机时 我看不到 使用 和 取消 按钮 void getCameraPicture UIImagePickerCon
  • R - 使用“rep”创建重复序列

    我想知道是否有更简单的方法来制作列表 例如 10 4 20 6 和 30 3 然后手写 example lt c 4 4 4 4 与函数 rep 我知道我可以重复某个序列 n 次 每次重复 n 次 但我不知道如何用每个数字的不同数量来制作一
  • O(n) 算法的计算时间可以超过 O(n^2) 吗?

    假设我有两种算法 for int i 0 i lt n i for int j 0 j lt n j do something in constant time 这自然是O n 2 假设我也有 for int i 0 i lt 100 i
  • 渐进式 Web 应用程序中的重定向

    我试图在通知单击时重定向到渐进式网络应用程序中的特定网址 但它不会重定向 情况 1 如果 Web 应用程序未添加到主屏幕 则在收到通知后单击浏览器窗口将打开并重定向到所需的 URL 情况 2 如果 Web 应用程序添加到主屏幕 则登陆页面是
  • PostgreSQL 9.1 时区

    我正在使用 postgresql 在数据库中存储一些日期 在我的应用程序中 它完全了解时区是至关重要的 我正在客户端 服务器和数据库之间进行一些基本测试 我从 GWT 中执行的浏览器应用程序发送日期 并读取 postgresql 上的日期
  • iTunes Connect - 无法邀请预发行应用程序的“内部测试人员”

    我的应用程序已获准通过新的 Apple TestFlight 应用程序进行分发 我试图通过邀请 内部测试员 iTunes Connect gt Prerelease gt Internal Testers但我看到的只是两个信息框 要开始测试
  • Pycharm 不接受“list[Example]”作为项目列表的类型提示[重复]

    这个问题在这里已经有答案了 我在 PyCharm 中发现了一个奇怪的类型 Example是我自己的班级 但我想这并不那么重要 因为 IDE 正在抱怨list类型没有定义 getitem 这是不正确的方法 我想知道这是一个错误还是我以错误的方
  • Magento - 对自定义报价总计字段应用税

    我为 Magento 创建了一个附加费模块 它在报价中添加了一个自定义总计字段 附加费含税输入到 Magento 中 我已成功获取将附加费添加到报价中的模块 并且结帐页面上的总计是正确的 当我尝试对附加费征税 以便将其包含并显示在结账页面的
  • jQuery Ajax Post 与数据

    当使用某些参数单击按钮时 我尝试调用 PHP 文件 它一直执行到 jsfile js 中的警报语句为止 之后ajax部分没有被执行 帮助我 主要 html
  • 当应用程序在后台运行时获取 GPS 位置更新

    我有一个 Android 应用程序 可以跟踪客户位置并每 10 秒发送一次位置 但是 在 android O 中 位置更新每小时会获得几次 正如有关 android O 中 GPS 位置更新限制的文档中所述 无论如何 为了克服这个问题 我使
  • C/C++ MPI 加速未达到预期

    我正在尝试编写一个 MPI 应用程序来通过计算机集群加速数学算法 但在此之前我正在做某种基准测试 但最初的结果并不像预期的那么好 测试应用程序在 4 核时具有线性加速 但 5 6 核并未加速应用程序 我正在使用 Odroid N2 平台进行
  • 在 Sympy.mpmath.plot 中更改图形大小

    我希望这个问题不是太初级 我已经广泛搜索了解决方案 但尚未找到 我最近开始使用 Jupyter Notebook 和 Sympy 在微积分 II 课上做笔记和做作业 这真是一个巨大的好处 然而 我唯一的问题是我无法弄清楚如何配置绘图的大小
  • 什么是堆栈溢出?

    什么是堆栈溢出错误 它可能出现在什么类型的程序 编程语言中 它不太可能出现在 Web 应用程序代码中吗 From 维基百科 http en wikipedia org wiki Stack overflow 在软件中 会发生堆栈溢出 当内存
  • 如果一个代理关闭,流应用程序中的 KafkaStream EXACTLY_ONCE 会导致重新平衡失败

    我有一个 Kafka 流应用程序 其中 kafka streams 和 kafka clients 均为 2 4 0 具有以下配置 properties put StreamsConfig BOOTSTRAP SERVERS CONFIG
  • jquery mouseover 和 mouseout 错误

    当我滚动一个元素 以查看包含该元素的总体数据 时 我试图获得某些内容的预览 并且当我推出时 一切都恢复原样 问题是 当我快速移动鼠标光标时 有时鼠标移出方法不会发生 并且数据保持更新 但我不希望出现这种情况 知道我该怎么做吗 documen
  • 垃圾收集期间崩溃的原因

    一段时间以来 我一直在努力解决 C 应用程序崩溃的问题 该应用程序也使用相当多的 C CLI 模块 这些模块主要是本地库的包装器来访问设备驱动程序 崩溃并不总是很容易重现 但我能够收集六个崩溃转储 这些崩溃转储表明程序总是在垃圾收集期间因访