簡體   English   中英

嘗試讀取寫保護的內存

[英]Attempted to read write protected memory

我有一個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()。

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#app時得到的最后一個異常: 例外

編輯:再次調試后,它停留在這里

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

出於某種原因, b1值始終為0。 插入的值 似乎因為這個原因我得到了受保護的內存錯誤。

我所做的只是復制存在recoveryChar()和convertChar()的所有方法,並將值作為參數傳遞。

我會探索那些東西:

  1. 你在C ++和C#方面有什么平台? 它們都是32位嗎? 兩個64位? 如果你有一個整數長度的混合,你可能會遇到錯誤的兩種語言之間的參數傳輸問題。 無論如何,最安全的選擇是使用例如'int32_t'而不僅僅是'int'來指定確切的整數寬度

  2. 有些人建議在使用例如“MarshalAs(UnmanagedType.LPStr)]字符串路徑”將c ++'char *'轉換為c#'字符串'時指定確切的編組器,請嘗試此操作

  3. 最后在C ++中添加一些“類似printf”的調試代碼,將各個步驟(包括調用開始時)的所有值轉儲到調試控制台。 您可以使用以下函數,該函數與printf一樣使用,但輸出到debuging控制台。

C ++中調試輸出的代碼示例:

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

  char buffer[1000];
  vsprintf(buffer, format, args);
  OutputDebugStringA(buffer);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM