Попытка чтения защищенной от записи памяти

У меня есть C++ DLL, которая экспортирует такой метод:

extern "C" __declspec (dllexport) void ConvE(int type, const char* path, int b1, int b2, int b3, int b4, int b5)
{
    FFileList file_list;

    char temp_path[1024];

    if(type == 1) 
    {
        sprintf(temp_path,"%s*",path);
        GetFindFileListWin(temp_path,".mrs",file_list);
        file_list.RecoveryZipE(b1, b2, b3, b4, b5);
        file_list.ConvertNameMRes2Zip();
    }
    else if(type == 2) 
    {
        sprintf(temp_path,"%s*",path);
        GetFindFileListWin(temp_path,".zip",file_list);
        file_list.ConvertZipE(b5, b4, b3, b2, b1);
        file_list.ConvertNameZip2MRes();
    }
}

И я вызываю его в свое приложение C# следующим образом:

[DllImport("Mrs.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void ConvE(int type, string path, int b1, int b2, int b3, int b4, int b5);

Но каждый раз, когда я запускаю его, он выдает ошибку "Попытка чтения или записи в защищенную память. Это часто указывает на то, что другая память повреждена"

Насколько я читал, что-то не так с тем, как я импортирую функцию в С#, но я действительно не знаю, как это решить.

Изменить: по умолчанию был Conv(), такой же, как мой ConvE, но без 5 целых чисел, и он отлично работает. Я сделал ConvE для использования file_list.RecoveryZipE(), который ранее при отладке накладывал меня на метод внутри этого, который называется RecvoeryCharE (я добавил его в свой код, вы можете взглянуть на него), а также тот, который был основан на RecoveryChar(), который работает с Conv().

RecoveryChar:

void RecoveryChar(char* pData,int _size)
{
    if(!pData) return;
    BYTE b,bh,d;

    for(int i=0;i<_size;i++) {
        b = *pData;
        bh = b&0x07;
        d = (bh<<5)|(b>>3);
        *pData = d ^ 0xff;
        pData++;
    }
} 

RecvoeryCharE:

void RecoveryCharE(char* pData, int _size, int b1, int b2, int b3, int b4, int b5)
{
    if(!pData) return;

    BYTE b;

    for(int i=0;i<_size;i++) {
        b = *pData;
        b = (((((b >> b1) | (b << 5)) ^ b2) + b3) ^ b4) - b5;
        *pData = b;
        pData++;
    }
} 

Последнее исключение, которое я получил при отладке приложения C#: Exception

Изменить: после повторной отладки он застрял здесь

RecoveryCharE( _fileheaderReader , _fileheaderReaderSize, b1, b2, b3, b4, b5 );

По какой-то причине значение b1 всегда принимает 0. Inserted valuesи кажется, что по этой причине я получаю ошибку защищенной памяти.

Все, что я сделал, это скопировал все методы, в которых присутствовали recoveryChar() и convertChar(), и передал значения в качестве параметров.


person Derezzed    schedule 25.03.2014    source источник
comment
Если вы измените тело функции на пустое, ошибка все еще возникает? Если да - что-то не так внутри функции. Если нет - что-то не так с импортом.   -  person Paweł Stawarz    schedule 25.03.2014
comment
Эта ошибка обычно возникает, когда вы пытаетесь получить доступ к несуществующему индексу в массиве, возможно, ваш список файлов пуст или вы запросили 4-й файл в списке только из 2 файлов.   -  person Eduardo Wada    schedule 25.03.2014
comment
@EduardoWada Я обновил свой вопрос, добавив дополнительную информацию, связанную с моей ошибкой, пожалуйста, посмотрите и спасибо за ответ.   -  person Derezzed    schedule 25.03.2014
comment
Это исключение говорит только о том, что это произошло в коде C++, вам придется отлаживать DLL C++, чтобы найти строку, в которой это происходит, и значения переменных, когда это происходит.   -  person Eduardo Wada    schedule 25.03.2014
comment
@EduardoWada Я загружаю результаты отладки. Еще раз спасибо за попытку помочь мне. Должен ли я публиковать исходные коды и свои правки?   -  person Derezzed    schedule 29.03.2014
comment
Не совсем уверен, может ли это быть проблемой, но ConvE получает const char *, а RecoveryCharE получает char * и пытается его изменить. Вы передаете строку, полученную ConvE, в RecoveryCharE? Если это так, вероятно, виртуальная машина C# недовольна изменением строки внутри нее.   -  person Leonardo    schedule 10.06.2014


Ответы (1)


Я бы исследовал эти вещи:

  1. Какая у вас платформа на C++ и на стороне C#? Они оба 32-битные? оба 64-битные? У вас может возникнуть проблема с передачей параметров между двумя языками, выполненной неправильно, если у вас смешанная целочисленная длина. В любом случае, самым безопасным было бы указать точную целочисленную ширину, используя, например, «int32_t» вместо «int».

  2. Некоторые люди предлагают указать точный маршаллер при преобразовании c++ 'char*' в c# 'string', используя, например, путь строки "MarshalAs(UnmanagedType.LPStr)]", попробуйте это

  3. Наконец, добавьте в C++ некоторый отладочный код, похожий на printf, чтобы выводить все значения на разных этапах (в том числе в начале вызова) в консоль отладки. Вы можете использовать следующую функцию, которая используется точно так же, как printf, но выводит на консоль отладки.

Пример кода для вывода отладки в C++:

inline void log_(const char *format, ...)
{
  va_list args;
  va_start(args, format);

  char buffer[1000];
  vsprintf(buffer, format, args);
  OutputDebugStringA(buffer);
}
person Eric Nicolas    schedule 23.07.2014