尝试读取写保护的内存

时间:2014-03-25 00:06:01

标签: c# c++ memory unmanaged

我有一个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时遇到的最后一个例外: Exception

编辑:再次调试后,它就停留在这里

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

出于某种原因, b1 值始终为0。 Inserted values 似乎因为这个原因我得到了受保护的内存错误。

我所做的只是复制存在recoveryChar()和convertChar()的所有方法,并将值作为参数传递。

1 个答案:

答案 0 :(得分:0)

我会探索这些事情:

  1. 您在C ++和C#方面的平台是什么?它们都是32位吗?两个64位?如果你有一个整数长度的混合,你可能会遇到错误的两种语言之间的参数传输问题。无论如何,最安全的选择是使用例如&#39; int32_t&#39;来指定确切的整数宽度。而不只是&#39; int&#39;

  2. 有些人建议在转换c ++&#39; char *&#39;时指定确切的编组程序。到c#&#39; string&#39;使用例如&#34; MarshalAs(UnmanagedType.LPStr)]字符串路径&#34;,请试试这个

  3. 最后添加一些&#34; printf-like&#34;调试C ++中的代码,将各个步骤(包括调用开始时)的所有值转储到调试控制台。您可以使用以下函数,该函数与printf一样使用,但输出到debuging控制台。

  4. C ++中调试输出的代码示例:

    inline void log_(const char *format, ...)
    {
      va_list args;
      va_start(args, format);
    
      char buffer[1000];
      vsprintf(buffer, format, args);
      OutputDebugStringA(buffer);
    }