总结:C# 尝试读取或写入受保护的内存,这通常指示其他内存已损坏。System.AccessViolationException

您所在的位置:网站首页 阻止访问受保护的内存 总结:C# 尝试读取或写入受保护的内存,这通常指示其他内存已损坏。System.AccessViolationException

总结:C# 尝试读取或写入受保护的内存,这通常指示其他内存已损坏。System.AccessViolationException

#总结:C# 尝试读取或写入受保护的内存,这通常指示其他内存已损坏。System.AccessViolationException| 来源: 网络整理| 查看: 265

1、是否运用到了unsafe模式下的非托管内存,是否有两个线程共同访问一个公共对象的情况

在unsafe模式操作非托管内存的情况下,第一个线程使用完这个对象就把这个对象清空,这时候第二个线程正在使用这个对象,就会因为内存中找不到这个内存区域而报错:“尝试读取或写入受保护的内存。这通常指示其他内存已损坏”。

在C#托管内存中,内存回收一般是有GC自动完成的,如果遇到找不到找不到对象的情况,报错信息是“未将对象引用设置到对象的实例”,而非托管内存的找不到对象报错信息是:尝试读取或写入受保护的内存。这通常指示其他内存已损坏。

因为一个非托管对象的操作方式是指针,当内存中的对象被清理掉时,这段内存地址就拒绝指针随意访问,这事指针如果继续访问这段内存,就会报尝试读取或写入受保护的内存这个错误

2、读取或写入受保护

dll文件应该是C++写的。封装了之后供我的C#程序调用,结果就提示了错误:尝试读取或写入受保护的内存。这通常指示其他内存已损坏。错误类型为:System.AccessViolationException。

跨线程操作引起的?因为我的dll控制的是硬件,应该绑定的是窗体句柄。我操作的时候是在一个事件event中操作的,大家知道event是另开线程的。  

private delegate void CloseDevDelegate(); private void CloseDev() { if (this.InvokeRequired) { CloseDevDelegate closeDev = new CloseDevDelegate(CloseDev); this.BeginInvoke(closeDev); } else { Program.DEVICE.CloseDev(); } } 在事件中使用:CloseDev()

在事件中使用:CloseDev()

3、在C#中调用别人的DLL的时候有时候出现 尝试读取或写入受保护的内存 。这通常指示其他内存已损坏。

在传值的时候还是用指针,再在C#中做转换就好了。

[DllImport("APPLISTCC.dll")] public static extern string TestFunc1(string param1); string ret1 = TestFunc1("text"); 改成: [DllImport("APPLISTCC.dll")] public static extern IntPtr TestFunc1(IntPtr par1); IntPtr ptrIn = Marshal.StringToHGlobalAnsi("text"); IntPtr ptrRet = TestFunc1(ptrIn); string retlust = Marshal.PtrToStringAnsi(ptrRet);

自己在程序里强制释放COM资源,调用Marshal.ReleaseComObject()方法将不再使用的对象释放掉

4、测试的可执行文件与 Windows 数据执行保护功能兼容

调用dll的程序,在运行时会出现 “尝试读取或写入受保护的内存。这通常指示其他内存已损坏。" 有关更多信息,请参见 /NXCOMPAT(与数据执行保护兼容)。 编译器中加入了对DEP的安全性检查,在编译完后的exe文件中取消NXCOMPAT位可解决该问题 editbin.exe /NXCOMPAT:NO myexe  

5、调用dll动态链接库的时候,参数类型是非常重要的,如果类型不对,就会出现本文这样的错误

C#中开始是这样的引入DLL的,参数分别是long类型与结构体类型,本身和DLL api里面的类型一样

在C#调用DLL动态链接库方法的时候,传值的时候自然也要做一些改变,引用类型的值要加入“ref”关键字,值类型(如com)则直接传入数字或变量名即可



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3