gpt4 book ai didi

c# - 在 Windows CE 6 上调试数据中止和预取中止异常

转载 作者:太空宇宙 更新时间:2023-11-03 21:50:54 25 4
gpt4 key购买 nike

我们在 Windows CE 和 Windows Mobile 上运行一个相当复杂的软件,用于在不同类型的设备上获取移动数据。在唯一安装了 Windows CE 6.0 的设备类型上,我们的客户端随机卡住操作系统(因此需要热启动)。客户端在卡住前可能运行良好一两天,但也可能运行五分钟(已检查句柄和内存泄漏)。在设备制造商的日志文件中,当设备卡住时会出现这样的条目:

Exception 'Data Abort' (4): Thread-Id=070a003e(pth=89ca07e0), Proc-Id=0709003e(pprc=8a01d3d0) 'OurClient.exe', VM-active=0709003e(pprc=8a01d3d0) 'OurClient.exe' PC=41a66b28(mscoree3_5.dll+0x00056b28) RA=41a64ab4(mscoree3_5.dll+0x00054ab4) SP=0003e28c, BVA=00000132

这些消息不时会有所不同(我会说到目前为止我数了 20 个不同的消息,但 kernel.dll、k.core.dll 或 nk.exe 中除外)。

所以我的问题基本上是,如何调试发生在.NET 框架和内核深处的这种错误?例如,如何将程序计数器转换为 mscorlib 中的方法(与返回地址相同)?我们的程序是否可能无法与 CE 6 一起正常工作,或者这也可能是驱动程序问题?

更新:事实证明,其中一个设备驱动程序干扰了我们的键盘 Hook 实现。

最佳答案

正如 Alan 指出的那样,如果您没有符号作为出现问题的来源(mscoree3_5.dll,您没有),那么中止信息将毫无用处。即使有了源代码,如果没有编译器符号输出,您也无法将其返回。

此时您只能进行有根据的猜测。异常信息看起来都有效(即 RA 或 SP 非零)这一事实向我表明这不是堆栈问题,更可能是数据问题(可能是对齐,可能是错误的读取或写入指针)。

我的猜测是它来自不正确的 P/Invoke。它“移动”的事实表明传递给 P/Invoke 的对象引用或地址可能由于收集或压缩而变得无效。

想象一下以下场景。

您有一个 native API,它接收指向某个数据 blob 的指针,该 API 不仅会立即使用,而且会定期使用。也许它从中读取或写入,但关键是 API 需要的数据不仅仅是在调用时同步。 API 必须存储该指针以供以后使用。

您创建一些通过 P/Invoke 调用此 API 的托管代码。要传递数据指针,您定义一个表示数据的类,创建该类的实例并将其传递。假设地址为 0x500。

您运行您的应用程序,调用 API,一切正常。 API 从 0x500 开始读取并开始其业务。

直到应用触发 GC。现在 GC 说“嘿,我的堆中有一些空白空间,我会移动一些东西来修复它”。它移动托管对象,使其现在位于 0x200 处,并释放 0x500 处的内存。在那之后的某个时候,API 转到它的指针,仍然在 0x500 并进行读取。操作系统说“嘿,那个未分配的空间,你不能那样做!”然后它中止。

解决此方案的方法是使用固定 GCHandle。您不是将类传递给 API,而是固定类并传入 GCHandle 的地址,GC 在收集或压缩期间无法移动该地址。这确保 GCHandle 的地址保持不变,并且可以安全地跨越 native 边界。

请注意,这种情况发生时根本没有使用不安全代码,尽管您可以对不安全代码执行相同的操作。事实上,我认为对于不安全的代码,您可能会更清楚它可能发生的位置,并且这可能比未标记为不安全的代码“更安全”。避免 unsafe 关键字并不能阻止不安全代码。

关于c# - 在 Windows CE 6 上调试数据中止和预取中止异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14610051/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com