Опит за четене на защитена от запис памет

Имам 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);

Но всеки път, когато го стартирам, ми извежда грешката „Опит за четене или запис на защитена памет. Това често е индикация, че друга памет е повредена“

Доколкото прочетох, нещо не е наред с начина, по който импортирам функцията в C#, но наистина не знам как да го реша.

Редактиране: по подразбиране имаше Conv(), който е същият като моя ConvE, но без 5-те цели числа, и този работи добре. Направих ConvE да използва file_list.RecoveryZipE(), който преди това при отстраняване на грешки ме подрежда върху метод вътре в този, наречен RecvoeryCharE (добавих го към кода си, можете да го разгледате) и също така този беше базиран на RecoveryChar(), който работи на Conv().

Char за възстановяване:

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#: Изключение

Редактиране: След повторно отстраняване на грешки, той остава тук

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

По някаква причина стойността b1 винаги приема 0. Вмъкнати стойностии изглежда, че поради тази причина получавам грешката в защитената памет.

Всичко, което направих, беше да копирам всички методи, където присъстваха 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++ кода, ще трябва да отстраните грешки в C++ DLL, за да намерите реда, където се случва, и стойностите на променливата, когато се случи.   -  person Eduardo Wada    schedule 25.03.2014
comment
@EduardoWada Качвам резултатите от отстраняването на грешки. Благодаря отново, че се опитахте да ми помогнете. Трябва ли да публикувам оригиналните кодове и моите редакции?   -  person Derezzed    schedule 29.03.2014
comment
Не съм сигурен дали това може да е проблемът, но ConvE получава const char *, а RecoveryCharE получава char * и се опитва да го промени. Предавате ли низа, получен от ConvE на RecoveryCharE? Ако това е така, вероятно C# VM не е доволна от промяната на низ в нея.   -  person Leonardo    schedule 10.06.2014


Отговори (1)


Бих проучил тези неща:

  1. Каква е вашата платформа от страна на C++ и от страна на C#? И двете 32-битови ли са? и двете 64 бита? Може да имате проблем с прехвърлянето на вашите параметри между двата езика, направено погрешно, ако имате комбинация от цели числа. Във всеки случай най-сигурният залог би бил да се посочи точната ширина на цялото число, като се използва например 'int32_t' вместо само 'int'

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

  3. Накрая добавете някакъв "подобен на printf" код за отстраняване на грешки във вашия C++, за да изхвърлите всички стойности на различни стъпки (включително само в началото на повикването) към конзолата за отстраняване на грешки. Можете да използвате следната функция, която се използва точно като 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