从C#到C++非托管代码的多个函数调用导致AccessViolationException
本文关键字:函数调用 AccessViolationException C++ 非托管代码 | 更新日期: 2023-09-27 18:19:38
我在C#程序中声明了一个DLL导入,如下所示:
[DllImport("C:''c_keycode.dll", EntryPoint = "generateKeyCode",
CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr generateKeyCode(char[] serial, char[] option, char c_type);
它引用了我的DLL中的函数generateKeyCode()
。
以下是导致错误的代码(使用了断点):
const char* generateKeyCode(char serial[],
char option[],
char c_type)
{
returnBufferString = "";
SHA1_CTX context;
int optionLength = 0;
#ifdef WIN32
unsigned char buffer[16384] = {0};
#else
unsigned char buffer[256] = {0};
#endif
//char output[80];
char keycode[OPTION_KEY_LENGTH+1] = "";
int digest_array_size = 10; //default value for digest array size
unsigned char digest[20] = {0};
char optx[24] = {0};
char c_type_upper;
// Combine serial # and Option or Version number
char str1[30] = {0};
int i;
int size = 0;
int pos = 0;
...
...
}
基本上,我导入了这个DLL,这样我就可以传递函数参数,它可以执行算法,只需返回一个结果。我使用了这个封送拆收器函数。。。
public static string genKeyCode_marshal(string serial, string option, char type)
{
return Marshal.PtrToStringAnsi(generateKeyCode(serial.ToCharArray(),
option.ToCharArray(), type));
}
这样我就可以正常地打电话了。在我的C++头文件中,我定义了一个字符串,如图所示,它有助于回答这个问题(它是C/C++函数顶部的returnBufferString
变量)。
当我使用NumericUpDown
控件以0.1的增量从1.0到9.9(每次向上或向下都伴随着另一个函数调用)时,我多次调用此函数,然后再次向下返回。然而,每次我尝试这样做时,程序都会在看似设定的函数调用次数后出现故障(如果我只是直接上下移动,则在返回时会在1.9处停止,如果我上下交替移动,则会更早停止)。
请注意,它有效,并给了我想要的价值,没有任何差异。
我将缓冲区大小更改为较小的数字(5012),当我尝试运行该程序时,在第一次函数调用时,它抛出了AccessViolationException。然而,与原始缓冲区相比,将缓冲区大小加倍到原始缓冲区的两倍(32768)没有任何影响——从1.0直接上升到9.9,然后再次下降,它在1.9处停止并抛出异常。
EDIT:默认值为ANSI,因此为ANSI。没有问题。这是内存分配问题吗??
我建议尝试以下操作:
[DllImport("C:''c_keycode.dll", EntryPoint = "generateKeyCode",
CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
static extern IntPtr generateKeyCode(string serial, string option, char c_type);
注意DllImport
属性的新CharSet
字段。
下一个想法是明确使用MarshalAs
属性:
[DllImport("C:''c_keycode.dll", EntryPoint = "generateKeyCode",
CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
static extern IntPtr generateKeyCode([MarshalAs(UnmanagedType.LPTStr)] string serial, [MarshalAs(UnmanagedType.LPTStr)] string option, char c_type);
我知道这可能不令人满意,但一旦我从C/C++DLL中删除了用于调试的输出重定向,问题就停止了。现在一切都正常了,所以我想这基本上相当于回答我自己的问题。感谢大家的回复。