Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble with C#<->C++ DLLImport "Attempted to read or write protected memory."

I have a C++ dll which has a function within it I am trying to call from a C# application.

Here's the code in the C++ header file

extern "C" _declspec(dllexport) int LabelStoringSSDsim(int devNum, UCHAR serial[40], UCHAR wwn[40],
                UCHAR ConfigID[5], UCHAR FrmRev[8], UCHAR DevName[40], int eCode);

Here's the code in the C++ source file

int LabelStoringSSDsim(int devNum, UCHAR serialLbl[40], UCHAR wwnLbl[40],
                UCHAR ConfigID[5], UCHAR FrmRev[8], UCHAR DevName[40], int eCode)
{

    string strConfigID="12111";                                     //5 bytes
    string strFrmRev="1.25....";                                    //8 bytes
    string strDevName="ABC-123.................................";   //40 bytes

    for (int i=0;i<5;i++)
        ConfigID[i] = strConfigID[i];

    for (int i=0;i<8;i++)
        FrmRev[i] = strFrmRev[i];

    for (int i=0;i<40;i++)
        DevName[i] = strDevName[i];
    return eCode;
}

Here's the C# relevant code

[DllImport("LabelStoring.dll")]
static extern int LabelStoringSSDsim(
    int devNum,
    byte[] strserial,
    byte[] strwwn,
    [In] ref byte[] ConfigID,
    [In] ref byte[] FrmRev,
    [In] ref byte[] DevName,
    int eCode
);


int errNum = LabelStoringSSDsim(devNum, bserial, bwwn, ref ConfigID, ref FrmRev, ref DevName, 123123);

So when I get to the last bit of code there I get the "Attempted to read or write protected memory. This is often an indication that other memory is corrupt." error.

I have no prior experience in importing DLL's like this and I've done a lot of searching but cannot seem to find a solution to the problem.

I tried starting over from scratch with a simple function returning an integer, and that worked. Then I added an int for me to pass to the function and it still worked. Then I added a byte array for me to pass, which worked. Then I attempted to turn that byte array into a reference and it failed. So my guess is I'm getting the data back incorrectly.

Any help is greatly appreciated.

like image 400
Chris Avatar asked Dec 09 '10 19:12

Chris


2 Answers

Try changing [In] to [In, Out]. I'm also not sure about using both the ref and [In, Out] keywords together on a single argument. (Edit: Hans Passant has a good explanation of the differences between the two in his comment below.)

See this MSDN article for more information, especially the passage, "By default, reference types (classes, arrays, strings, and interfaces) passed by value are marshaled as In parameters for performance reasons. You do not see changes to these types unless you apply InAttribute and OutAttribute (or just OutAttribute) to the method parameter."

like image 195
Sam Skuce Avatar answered Oct 18 '22 06:10

Sam Skuce


I started getting this exception durring native interop periodically after upgrading to Windows 7. The code had always worked on XP and has fewer issues on Win 7 if I ran my app in XP compatibility mode.

After some research and experimentation I discovered that the reason I was getting this exception had to do with calling a native function that returned a string (WCHAR*).

I don’t believe there is currently a fix for this as even updating to .Net 3.5 didn’t fix the issue… However I did find the following work around.

Example of what works on XP but doesn’t work on Win 7:

[DllImport("NativeBin.dll")]
public static extern String GetWCharStr();

Example of what works for me on Win 7 and XP:

[DllImport("NativeBin.dll")]
private static extern IntPtr GetWCharStr();
public static String GetString()
{
    return Marshal.PtrToStringUni(GetWCharStr());
}
like image 40
Gabe J Avatar answered Oct 18 '22 05:10

Gabe J