我正在开发一个用C#编写的项目,并使用C ++ dll与机器人进行通信。最初该软件是用C#VS 2003编写的,并使用.Net 2.0转换为VS 2008(无需更改代码)。现在,我开始在某些计算机上看到“试图读取或写入受保护的内存......”。当代码从dll调用特定方法时,总是抛出Access违规错误,但是,在整个任务中反复调用相同的方法并执行正常,有时它会抛出错误。此外,机器人似乎执行命令fine,它告诉我传递给dll的值存在,因此可以访问。
带有.Net 1.1的软件已使用多年,并且工作正常,没有丢失任何内存错误。现在它一直在使用.Net 2.0,它只会在某些计算机上抛出错误。
我不确定是什么导致了这个问题。我排除了dll方法的不恰当的调用(不正确的编组...),因为它已经与.Net 1.1一起工作多年,因此在.Net 2.0中也应该可以正常工作。我已经看到一些帖子暗示它可能是GC,但是又一次为什么它只会发生在这台计算机上而且有时只会发生。此外,传入的值是C#代码中的所有全局变量,因此它们应该存在,直到应用程序关闭并且GC没有业务移动任何这些或删除它们。另一个观察,如上所述,机器人正常执行命令,这意味着它获得了所有必要的值。不确定C ++ dll的方法在GC可能搞乱内容的最后会做什么。它不应该尝试删除传入的全局变量,并且方法也没有修改那些变量(我不期望通过传入的值返回任何值,唯一的返回值是方法返回,它也不应该有与GC有关。)
我应该添加的一条重要信息是我无法访问C ++代码,因此无法进行任何更改。
修复必须通过C#代码或计算机上的某些设置或我控制的其他内容。 任何帮助非常感谢。 感谢。
代码段: VS 2003中的原始方法调用
[DllImport("TOOLB32.dll",EntryPoint="TbxMoveWash")]
public static extern int TbxMoveWash(int tArmId, string lpszCarrierRackId,
int eZSelect, int[] lpTipSet, int tVol, bool bFastW);
我在看到以下错误后修改了(但错误仍然发生):
[DllImport("TOOLB32.dll",EntryPoint="TbxMoveWash")]
public static extern int TbxMoveWash(int tArmId, string lpszCarrierRackId,
int eZSelect, [MarshalAs(UnmanagedType.LPArray, SizeConst = 8)] int[] lpTipSet, int tVol, bool bFastW);
答案 0 :(得分:0)
C ++ DLL实际上可能会引发访问冲突,因此问题根本不在.NET中。你能在发生异常时停止,捕获输入并尝试从非托管代码中重现问题吗?
如果你确定它在编组中:int是非常安全的,所以有两个嫌疑人 - 字符串和数组参数。如果您不希望收到任何数据,我会标记具有[In]
属性的那些数据,因此.NET甚至不会尝试编组数据。然后SizeConst
变得无关紧要。
如果没有解决问题,请尝试为字符串指定[MarshalAs]
,一旦您(以某种方式)找出C ++ DLL所期望的字符串类型。此外,它是ANSI还是Unicode?您可能需要在CharSet
中指定[DllImport]
。
这也可能是.NET CLR中的一个错误(在2.0版中引入)。禁用优化时是否会出现问题(Debug build)?