0xC0000005 是访问冲突,因此某些东西正试图读取或写入它无权访问的地址。这些往往很难找到,经验是最好的工具之一(好吧,Platform Builder 的调试器也很有帮助,但这是一个完全独立的调试途径,需要你可能没有或已经有的经验试过了)。我发现日志记录往往不如减法编码有用 - 尽可能使用模拟托管调用删除 P/invoke 调用。
托管应用程序中的访问冲突通常由于以下原因之一发生:
- 您 P/Invoke 将句柄传递给托管对象的本机 API,并且本机 API 使用该句柄。如果在本机 API 运行时获得集合和压缩,则托管对象可能会移动并且指针变得无效。
- 您 P/Invoke 的缓冲区太小或小于您传入的大小,并且 API 超出了读取或写入
- 传递给 P/Invoke 调用的指针(IntPtr 等)无效(-1 或 0),并且本机在使用前未对其进行检查
- 您 P/Invoke 本机调用并且本机代码耗尽内存(通常是虚拟的)并且不检查失败的分配和读取/写入无效地址
- 您使用未初始化的 GCHandle 或以某种方式指向已完成并收集的对象(因此它不是指向对象,而是指向对象曾经所在的地址)
- 您的应用使用句柄来处理因睡眠/唤醒而无效的内容。这更深奥,但肯定会发生。例如,如果您在存储卡上运行应用程序,则整个应用程序不会加载到 RAM 中。使用中的部分被按需调入执行。这一切都很好。现在,如果您关闭设备电源,驱动程序将全部关闭。当您重新启动电源时,许多设备只需重新安装存储设备即可。当您的应用程序需要在更多程序中请求页面时,它不再是它原来的位置并且它死了。安装存储上的数据库可能会发生类似的行为。如果您有数据库的打开句柄,则在睡眠/唤醒周期后,连接句柄可能不再有效。
You'll note the trend here that almost all of these are P/Invokes and that's no accident. It's quite difficult to get managed code to do this on its own.