我正在尝试调查一个非常严重的软件崩溃,这可能与托管堆损坏有关(因为它发生在垃圾收集期间)。将 WinDbg 与 (SOS) !gchandles 命令一起使用,我得到类似的信息
0:000> !gchandles
GC Handle Statistics:
Strong Handles: 259
Pinned Handles: 137
Async Pinned Handles: 1
Ref Count Handles: 79
Weak Long Handles: 197
Weak Short Handles: 650
Other Handles: 0
Statistics:
我只是很好奇,“普通”固定手柄和“异步固定”手柄有什么区别?我能找到我的哪个句柄是“异步”句柄吗?
我在网上找不到任何有关它的信息,因为当该计数器恰好为 1 时,应用程序似乎总是崩溃,因此可能与崩溃有关。但话又说回来,它可能只是垃圾收集期间使用的一些内部东西。
异步固定句柄与 Windows 中的重叠 I/O 密切相关。它支持使用 ReadFile 和 WriteFile 进行异步读取和写入,并使用 OVERLAPPED 参数。设备驱动程序存储传递的缓冲区指针,并直接从缓冲区读取/写入缓冲区,完全与程序操作异步。托管包装方法是 BeginRead 和 BeginWrite。
如果缓冲区是在 GC 堆中分配的,则需要将其固定,直到驱动程序完成使用缓冲区。让 GC 移动缓冲区while驱动程序正在处理 I/O 传输,这是灾难性的,写入会产生垃圾,读取会损坏 GC 堆,需要固定以防止驱动程序使用缓冲区时移动缓冲区。
固定的物体非常令人不快,当垃圾收集器压缩堆时,它们使垃圾收集器很难在道路上的岩石周围工作。这里有一个必要的罪恶,唯一可能的方法就是让缓冲区固定尽可能短的时间。
异步固定句柄经过专门标记,以允许 CLR 在 I/O 完成时自动取消固定缓冲区。当 I/O 完成端口发出完成信号时尽快,因此不必等待客户端代码执行回调并取消固定缓冲区。当有大量正在运行的线程池线程时,这可能需要一段时间。当您拥有处理数万个客户端请求的 Web 服务器时,这是一种微观优化,往往会变成宏观优化。
它仅用于 System.Threading.OverlappedData 类型的对象,这是 mscorlib.dll 中的一个内部类,CLR 对它有专门的了解,并且是 Windows api 函数使用的本机 OVERLAPPED 结构的托管传真。
长话短说,您真正知道的是,如果您在崩溃时看到句柄计数为 1,则有一个重叠的 I/O 待处理。拥有任何与 gc 分配的未固定缓冲区重叠 I/O 的本机代码确实是销毁堆的好方法。顺便说一句,你有很多固定的手柄。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)