Многократные вызовы функций из неуправляемого кода C # к C ++ вызывают AccessViolationException - PullRequest
6 голосов
/ 05 января 2012

Я объявил импорт DLL в моей программе на C #, который выглядит следующим образом:

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

Он ссылается на функцию generateKeyCode() внутри моей DLL.

Вот код, который вызывает ошибку (используемые точки останова):

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 ++ я определил строку, как указано, полезно в ответе на этот вопрос (это переменная returnBufferString в верхней части функции C / C ++).

Я выполняю этот вызов функции несколько раз, так как использую элемент управления NumericUpDown для перехода от 1,0 до 9,9 с шагом 0,1 (каждый вверх или вниз сопровождает другой вызов функции), а затем снова вниз.Однако каждый раз, когда я пытаюсь это сделать, программа срабатывает после, казалось бы, установленного количества вызовов функций (останавливается на уровне 1,9 на пути назад, если я просто иду прямо вверх и вниз, или раньше, если я чередую вверх и вниз немного),

Обратите внимание, что это работает и дает мне требуемое значение, там нет никаких расхождений.

Я изменил размер буфера на несколько меньшее число (5012), и когда я попытался запуститьПрограмма, при первом вызове функции она вызвала AccessViolationException.Однако удвоение размера буфера до двойного (32768) оригинала не дало эффекта по сравнению с оригиналом - при прямом увеличении до 9,9 с 1,0 и обратно он останавливается на 1,9 и выдает исключение.

РЕДАКТИРОВАТЬ: по умолчанию ANSI, поэтому это ANSI.Там нет проблем.Это проблема выделения памяти ??

Ответы [ 2 ]

2 голосов
/ 05 января 2012

Я бы предложил попробовать следующее:

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

Обратите внимание на новое поле CharSet атрибута DllImport.

Следующая идея - использовать атрибут 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);
0 голосов
/ 08 января 2012

Я знаю, что это может быть неудовлетворительно, но как только я удалил перенаправление вывода, которое я использовал для отладки из моей C / C ++ DLL, проблема прекратилась. Теперь все работает, поэтому я думаю, что это по сути эквивалентно ответу на мой собственный вопрос. Спасибо всем за ответы.

...