从 C# 到 C++ 的多个函数调用非托管代码导致 AccessViolationException

发布于 2024-12-24 21:21:15 字数 1936 浏览 1 评论 0 原文

我已在 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 处,或者如果我稍微上下交替,则在返回时停止在 1.9 处) 。

请注意,它有效并为我提供了我想要的值,没有任何差异。

我将缓冲区大小更改为较小的数字(5012),当我尝试运行该程序时,在第一个函数调用时它抛出了 AccessViolationException。然而,将缓冲区大小加倍到原始缓冲区大小的两倍 (32768) 与原始缓冲区大小相比没有任何效果 - 从 1.0 直接上升到 9.9,然后再次下降,它在 1.9 处停止并抛出异常。

编辑:默认是 ANSI,所以它是 ANSI。那里没有问题。这是内存分配问题吗?

I have declared a DLL import in my C# program that looks like this:

[DllImport("C:\\c_keycode.dll", EntryPoint = "generateKeyCode", 
           CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr generateKeyCode(char[] serial, char[] option, char c_type);

It references the function generateKeyCode() inside of my DLL.

Here is the code that is causing an error (used breakpoints):

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;


...
...
}

Basically, I imported this DLL so I could pass the function parameters and it could do its algorithm and simply return me a result. I used this marshaler function...

public static string genKeyCode_marshal(string serial, string option, char type)
{
    return Marshal.PtrToStringAnsi(generateKeyCode(serial.ToCharArray(), 
           option.ToCharArray(), type));
}

...so I could make the call properly. Inside of my C++ header file, I have defined a string, as indicated is helpful in the answer to this question (it is the returnBufferString variable present at the top of the C/C++ function).

I make this function call several times as I use a NumericUpDown control to go from 1.0 to 9.9 in increments of 0.1 (each up or down accompanies another function call), and then back down again. However, every time I try to do this, the program hitches after a seemingly set number of function calls (stops at 1.9 on the way back down if I just go straight up and down, or earlier if I alternate up and down a bit).

Please note that it works and gives me the value I want, there are no discrepancies there.

I changed the buffer size to some smaller number (5012) and when I tried to run the program, on the first function call it threw the AccessViolationException. However, doubling the buffer size to twice (32768) the original had no effect in comparison to the original -- going straight up to 9.9 from 1.0 and down back again, it stops at 1.9 and throws the exception.

EDIT: Default is ANSI, so it is ANSI. No problems there. Is this a memory allocation issue??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

饮惑 2024-12-31 21:21:15

我建议尝试以下操作:

[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);

I would suggest trying the following:

[DllImport("C:\\c_keycode.dll", EntryPoint = "generateKeyCode", 
       CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
static extern IntPtr generateKeyCode(string serial, string option, char c_type);

Note the new CharSet field of DllImport attribute.

Next idea is to use MarshalAs attribute explicitely:

[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);
旧城烟雨 2024-12-31 21:21:15

我知道这可能不能令人满意,但是一旦我删除了用于从 C/C++ DLL 中调试的输出重定向,问题就停止了。现在一切正常,所以我想这基本上等同于回答我自己的问题。感谢大家的回复。

I know this may be unsatisfactory, but once I removed the output redirection I was using to debug from within my C/C++ DLL, the problem stopped. Everything works now, so I guess that's essentially equivalent to answering my own question. Thanks to everyone for the replies.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文