2014-03-25 154 views
4

我有一個C++動態鏈接庫導出這樣的方法:試圖讀取寫入保護內存

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的一個方法中(我將它添加到我的代碼中,您可以看一看),還有一個是base在Conv()上工作的RecoveryChar()上。

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

出於某種原因stucks再次調試完畢,B1值始終走0。 Inserted values 似乎出於這個原因,我得到了受保護的內存錯誤。

我所做的只是複製recoveryChar()和convertChar()所在的所有方法,並將值作爲參數傳遞。

+1

如果改變函數體是空的,沒有錯誤仍時有發生?如果是 - 功能內部有問題。如果沒有 - 導入它有什麼問題。 –

+0

當您嘗試訪問數組中的一個不存在的索引時,通常會發生此錯誤,也許您的文件列表爲空,或者您要求列出僅包含兩個文件的第4個文件 –

+0

@EduardoWada我更新了我的問題有關我的錯誤的信息,請看看並感謝您的回覆。 – Derezzed

回答

0

我想探討那些事:

  1. 你有什麼平臺上的C++和C#的一面呢?他們都是32位嗎?兩個64位?如果混合使用整數長度,那麼在兩種語言之間的參數傳輸完成時您可能會遇到問題。無論如何,最安全的賭注是使用例如'int32_t'而不是'int'來指定確切的整數寬度。

  2. 有人建議在將C++'char *'轉換爲c#'字符串'時指定確切的marshaller實例「MarshalAs(UnmanagedType.LPStr)] string path」,請嘗試此操作

  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); 
} 
相關問題