我有一个很奇怪的问题:
我正在使用 NUnit 测试对非托管 C dll 的几个函数调用。奇怪的是,测试在正常运行时失败,但是当我用调试器运行它时(即使没有断点)它通过了。
那么,调试器是否像普通的 NUnit 应用程序一样拥有更广泛的内存访问权限?
我已经隔离了失败的呼叫。它传回一个指向字符串的 char 指针,编组器应将其转换为 C# 字符串。C端看起来像这样:
#define get_symbol(a) ((a).a_w.w_symbol->s_name)
EXTERN char *atom_get_symbol(t_atom *a);
...
char *atom_get_symbol(t_atom *a) {
return get_symbol(*a);
}
和 C# 代码:
[DllImport("csharp.dll", EntryPoint="atom_get_symbol")]
[return:MarshalAs(UnmanagedType.LPStr)]
private static extern string atom_get_symbol(IntPtr a);
从 c 返回的指针在代码和列表的一部分中非常深入。所以我只是想念一些安全设置吗?
编辑:这是我得到的例外:
System.AccessViolationException :(翻译成英文:)试图读取或写入受保护的内存。这可能表明其他内存已损坏。
at Microsoft.Win32.Win32Native.CoTaskMemFree(IntPtr ptr)
at ....atom_get_symbol(IntPtr a)
解决方案:
问题是,编组器想要释放作为 C 结构一部分的内存。但它应该只是复制字符串并保持原样:
[DllImport("csharp.dll", EntryPoint="atom_get_symbol")]
private static extern IntPtr atom_get_symbol(IntPtr a);
然后在代码中获取字符串的副本:
var string = Marshal.PtrToStringAnsi(atom_get_symbol(ptrToStruct));
伟大的!