System.AccessViolationException:尝试读取或写入受保护的内存

时间:2011-04-14 14:28:57

标签: c# c++ wrapper

我有一个从C ++非托管库开始生成C#包装器的问题。每次我陷入System.AccessViolationException:尝试读取或写入受保护的内存。我知道这可能取决于我将结构及其元素从C ++转换为C#的方式,但我不知道如何解决。 有人能帮助我吗?

C ++代码:

typedef struct VBLEnvironmentVariable_t
{
VBLObjectHeader mHeader;                     
DWORD           mNameLength;                 
DWORD           mDataLength;                 
LPSTR           mName;                       
LPBYTE          mData;                       
} VBLEnvironmentVariable;

typedef struct VBLAppTrigger_t
{
VBLObjectHeader mHeader;                     
ULONGLONG       mPreTriggerTime;             
ULONGLONG       mPostTriggerTime;            
WORD            mChannel;                    
WORD            mFlags;                      
DWORD           mAppSecific2;                
} VBLAppTrigger;

//signature
BLAPI( BOOL)   BLWriteObject( HANDLE hFile, VBLObjectHeaderBase* pBase);


//how function is called

int write_test( LPCTSTR pFileName, LPDWORD pWritten)
{

if ( NULL == pWritten)
{
    return -1;
}

*pWritten = 0;

/* open file */
hFile = BLCreateFile( pFileName, GENERIC_WRITE);

if ( INVALID_HANDLE_VALUE == hFile)
{
    return -1;
}

/* set applicaton information */
/* bSuccess = BLSetApplication( hFile, BL_APPID_UNKNOWN, 1, 0, 0); */
bSuccess = BLSetApplication( hFile, BL_APPID_CANCASEXLLOG, 1, 0, 1);

GetSystemTime( &systemTime);

bSuccess = bSuccess && BLSetMeasurementStartTime( hFile, &systemTime);

/* set write options */
bSuccess = bSuccess && BLSetWriteOptions( hFile, 6, 0);


if ( bSuccess)
{
    // setup object headers 
    appTrigger.mHeader.mBase.mSignature = BL_OBJ_SIGNATURE;
    appTrigger.mHeader.mBase.mHeaderSize = sizeof( appTrigger.mHeader);
    appTrigger.mHeader.mBase.mHeaderVersion = 1;
    appTrigger.mHeader.mBase.mObjectSize = sizeof( VBLAppTrigger);
    appTrigger.mHeader.mBase.mObjectType = BL_OBJ_TYPE_APP_TRIGGER;
    appTrigger.mHeader.mObjectFlags = BL_OBJ_FLAG_TIME_ONE_NANS;

    message.mHeader.mBase.mSignature = BL_OBJ_SIGNATURE;
    message.mHeader.mBase.mHeaderSize = sizeof( message.mHeader);
    message.mHeader.mBase.mHeaderVersion = 1;
    message.mHeader.mBase.mObjectSize = sizeof( VBLCANMessage);
    message.mHeader.mBase.mObjectType = BL_OBJ_TYPE_CAN_MESSAGE;
    message.mHeader.mObjectFlags = BL_OBJ_FLAG_TIME_ONE_NANS;

    variable_s.mHeader.mBase.mSignature = BL_OBJ_SIGNATURE;
    variable_s.mHeader.mBase.mHeaderSize = sizeof( variable_s.mHeader);
    variable_s.mHeader.mBase.mHeaderVersion = 1;
    variable_s.mHeader.mBase.mObjectType = BL_OBJ_TYPE_ENV_STRING;
    variable_s.mHeader.mObjectFlags = BL_OBJ_FLAG_TIME_ONE_NANS;

    variable_i.mHeader.mBase.mSignature = BL_OBJ_SIGNATURE;
    variable_i.mHeader.mBase.mHeaderSize = sizeof( variable_i.mHeader);
    variable_i.mHeader.mBase.mHeaderVersion = 1;
    variable_i.mHeader.mBase.mObjectType = BL_OBJ_TYPE_ENV_INTEGER;
    variable_i.mHeader.mObjectFlags = BL_OBJ_FLAG_TIME_ONE_NANS;

    ethframe.mHeader.mBase.mSignature = BL_OBJ_SIGNATURE;
    ethframe.mHeader.mBase.mHeaderSize = sizeof( ethframe.mHeader);
    ethframe.mHeader.mBase.mHeaderVersion = 1;
    ethframe.mHeader.mBase.mObjectType = BL_OBJ_TYPE_ETHERNET_FRAME;
    ethframe.mHeader.mObjectFlags = BL_OBJ_FLAG_TIME_ONE_NANS;

    appText.mHeader.mBase.mSignature = BL_OBJ_SIGNATURE;
    appText.mHeader.mBase.mHeaderSize = sizeof( appText.mHeader);
    appText.mHeader.mBase.mHeaderVersion = 1;
    appText.mHeader.mBase.mObjectType = BL_OBJ_TYPE_APP_TEXT;
    appText.mHeader.mObjectFlags = BL_OBJ_FLAG_TIME_ONE_NANS;

    for ( i = 0; i < 1000; ++i)
    {
        ethbuffer[i] = ( BYTE)i;
    }

    for ( i = 0; i < 1000 && bSuccess; ++i)
    {
        // increment in milliseconds 
        time = i * 10000000;

        // setup app trigger object header 
        appTrigger.mHeader.mObjectTimeStamp = time;

        // write app trigger object 
        bSuccess = BLWriteObject( hFile, &appTrigger.mHeader.mBase);
        *pWritten += bSuccess ? 1 : 0;

        // setup CAN object header 
        message.mHeader.mObjectTimeStamp = time;

        // setup CAN message 
        message.mChannel = 1;
        message.mFlags = CAN_MSG_FLAGS( 0, 0);
        message.mDLC = 8;
        message.mID = 0x100;
        memcpy( message.mData, ( i % 2) ? _T( "01234567") : _T( "76543210"), message.mDLC);

        // write CAN message 
        bSuccess = BLWriteObject( hFile, &message.mHeader.mBase);
        *pWritten += bSuccess ? 1 : 0;

        if ( 0 == ( i % 3) && bSuccess)
        {
            // setup environment variable object headers 
            variable_s.mHeader.mObjectTimeStamp = time;
            variable_i.mHeader.mObjectTimeStamp = time;

            // setup environment variables 
            variable_s.mNameLength = strlen( ENV_NAME1);
            variable_s.mDataLength = strlen( ( i % 2) ? ENV_DATA1 : ENV_DATA2);
            variable_s.mName = ENV_NAME1;
            variable_s.mData = ( i % 2) ? ENV_DATA1 : ENV_DATA2;
            variable_s.mHeader.mBase.mObjectSize = sizeof( VBLEnvironmentVariable) + variable_s.mNameLength + variable_s.mDataLength;

            variable_i.mNameLength = strlen( ENV_NAME2);
            variable_i.mDataLength = sizeof( int);
            variable_i.mName = ENV_NAME2;
            variable_i.mData = ( LPBYTE)&i;
            variable_i.mHeader.mBase.mObjectSize = sizeof( VBLEnvironmentVariable) + variable_i.mNameLength + variable_i.mDataLength;

            // write environment variables 
            bSuccess = BLWriteObject( hFile, &variable_s.mHeader.mBase);
            *pWritten += bSuccess ? 1 : 0;

            bSuccess = bSuccess && BLWriteObject( hFile, &variable_i.mHeader.mBase);
            *pWritten += bSuccess ? 1 : 0;

            // write ethernet frame 
            memcpy( ethframe.mSourceAddress, src, sizeof( ethframe.mSourceAddress));
            ethframe.mReserved1 = 0;
            memcpy( ethframe.mDestinationAddress, dst, sizeof( ethframe.mDestinationAddress));
            ethframe.mReserved2 = 0;
            ethframe.mType = 0x0800;
            ethframe.mTPID = 0;
            ethframe.mTCI = 0;
            ethframe.mPayLoadLength = ( WORD)i;
            ethframe.mPayLoad = ethbuffer;
            ethframe.mHeader.mBase.mObjectSize = sizeof( VBLEthernetFrame) + ethframe.mPayLoadLength;

            bSuccess = bSuccess && BLWriteObject( hFile, &ethframe.mHeader.mBase);
            *pWritten += bSuccess ? 1 : 0;

            // write text 
            if ( ( i % 100) == 0)
            {
                char text[128];

                sprintf( text, "%d objects written...", *pWritten);

                appText.mText = text;
                appText.mTextLength = strlen( appText.mText);
                appText.mHeader.mBase.mObjectSize = sizeof( VBLAppText) + appText.mTextLength;

                bSuccess = bSuccess && BLWriteObject( hFile, &appText.mHeader.mBase);
                *pWritten += bSuccess ? 1 : 0;
            }
        }
    }

    appText.mText = "All objects written...";
    appText.mTextLength = strlen( appText.mText);
    appText.mHeader.mBase.mObjectSize = sizeof( VBLAppText) + appText.mTextLength;

    bSuccess = bSuccess && BLWriteObject( hFile, &appText.mHeader.mBase);
    *pWritten += bSuccess ? 1 : 0;
}

/* close file */
if ( !BLCloseHandle( hFile))
{
    return -1;
}

return bSuccess ? 0 : -1;
}`

C#代码:

//translation of C++ struct into C# class

public class VBLEnvVar 
{
public VBLEnvVarStruct variable_s;

public VBLEnvVar()
{
    variable_s = new BLF_Function.VBLEnvVar.VBLEnvVarStruct();
}

public  struct VBLEnvVarStruct
{

    public VBLObjectHeader.VBLObjectHeaderStruct mHeader;
    public uint NameLength;
    public uint DataLength;
    public string Name;
    [MarshalAsAttribute(UnmanagedType.LPArray)]
    public byte[] Data;

}

}

public class VBLAppTrigger 
{

public VBLAppTriggerStruct apptrigger;
public VBLAppTrigger()
{
    apptrigger = new BLF_Function.VBLAppTrigger.VBLAppTriggerStruct(null);
}
public struct VBLAppTriggerStruct
{

    public VBLObjectHeader.VBLObjectHeaderStruct mHeader;
    public UInt64 mPreTriggerTime;
    public UInt64 mPostTriggerTime;
    public ushort mFlags;
    public ushort mChannel;
    public uint mAppSpecific2;

}

}

[DllImport("binlog.dll")]
public static extern bool BLWriteObject( int Handle,ref  BLF_Function.ObjectHeader.ObjHeader pBase);


//how function is called into C# code

public static void Main(string[] args)
{
int written=0;
BLF_Function b = new BLF_Function();
UInt64 time=0;
byte[] ethbuffer = new byte[1500];
bool success=false;

string filename = "provamia.blf";

int Handle = MyBLF.BLCreateFile(filename,b.GENERIC_WRITE);
if (Handle != -1)
{
    success = MyBLF.BLSetApplication( Handle, (byte)BLF_Function.FileStatistics.APPID.BL_APPID_UNKNOWN, 1, 0, 1);

    //***********
    MyBLF.SYSTEMTIME d = new MyBLF.SYSTEMTIME();

    MyBLF.GetLocalTime(out d);
    MyBLF.SYSTEMTIME* s = &d;

    success = MyBLF.BLSetMeasurementStartTime( Handle,ref s);
    //*************

    if (success)
    {
        success = MyBLF.BLSetWriteOptions( Handle, 6,0);
        if (success)
        {

            BLF_Function.VBLObjectHeader vblobjectheaderclass = new BLF_Function.VBLObjectHeader();
            BLF_Function.ObjectHeader objectheaderclass = new BLF_Function.ObjectHeader();
            vblobjectheaderclass.mHeader.baseheader=objectheaderclass.baseheader;

            BLF_Function.VBLAppTrigger apptriggerclass = new BLF_Function.VBLAppTrigger();
            apptriggerclass.apptrigger.mFlags=(ushort)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;
            apptriggerclass.apptrigger.mHeader=vblobjectheaderclass.mHeader;
            apptriggerclass.apptrigger.mHeader.baseheader.HeaderSize = apptriggerclass.apptrigger.mHeader.GetSize();
            apptriggerclass.apptrigger.mHeader.baseheader.HeaderVersion = 1;
            apptriggerclass.apptrigger.mHeader.baseheader.signature = objectheaderclass.BL_OBJ_SIGNATURE;
            apptriggerclass.apptrigger.mHeader.baseheader.ObjectSize = (ushort)apptriggerclass.GetSize();
            apptriggerclass.apptrigger.mHeader.baseheader.ObjectType = (ushort)BLF_Function.ObjectHeader.OBJ_TYPR.BL_OBJ_TYPE_APP_TRIGGER;
            apptriggerclass.apptrigger.mHeader.mObjectFlags = (uint)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;

            BLF_Function.VBLCANMessage messageclass = new BLF_Function.VBLCANMessage();
            messageclass.message.mHeader=vblobjectheaderclass.mHeader;
            messageclass.message.mHeader.baseheader.HeaderSize = messageclass.message.mHeader.GetSize();
            messageclass.message.mHeader.baseheader.HeaderVersion = 1;
            messageclass.message.mHeader.baseheader.signature = objectheaderclass.BL_OBJ_SIGNATURE;
            messageclass.message.mHeader.baseheader.ObjectSize = (ushort)messageclass.GetSize();
            messageclass.message.mHeader.baseheader.ObjectType = (ushort)BLF_Function.ObjectHeader.OBJ_TYPR.BL_OBJ_TYPE_CAN_MESSAGE;
            messageclass.message.mHeader.mObjectFlags = (uint)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;

            BLF_Function.VBLEnvVar variable_sclass = new BLF_Function.VBLEnvVar();
            variable_sclass.variable_s.mHeader=vblobjectheaderclass.mHeader;
            variable_sclass.variable_s.mHeader.baseheader.HeaderSize = variable_sclass.variable_s.mHeader.GetSize();
            variable_sclass.variable_s.mHeader.baseheader.HeaderVersion = 1;
            variable_sclass.variable_s.mHeader.baseheader.signature = objectheaderclass.BL_OBJ_SIGNATURE;
            variable_sclass.variable_s.mHeader.baseheader.ObjectType = (ushort)BLF_Function.ObjectHeader.OBJ_TYPR.BL_OBJ_TYPE_ENV_STRING;
            variable_sclass.variable_s.mHeader.mObjectFlags = (uint)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;

            BLF_Function.VBLEnvVar variable_iclass = new BLF_Function.VBLEnvVar();
            variable_iclass.variable_s.mHeader=vblobjectheaderclass.mHeader;
            variable_iclass.variable_s.mHeader.baseheader.HeaderSize = variable_iclass.variable_s.mHeader.GetSize();
            variable_iclass.variable_s.mHeader.baseheader.HeaderVersion = 1;
            variable_iclass.variable_s.mHeader.baseheader.signature = objectheaderclass.BL_OBJ_SIGNATURE;
            variable_iclass.variable_s.mHeader.baseheader.ObjectType = (ushort)BLF_Function.ObjectHeader.OBJ_TYPR.BL_OBJ_TYPE_ENV_INTEGER;
            variable_iclass.variable_s.mHeader.mObjectFlags = (uint)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;

            BLF_Function.VBLEthernetFrame ethframeclass = new BLF_Function.VBLEthernetFrame();
            ethframeclass.ethframe.mHeader=vblobjectheaderclass.mHeader;
            ethframeclass.ethframe.mHeader.baseheader.HeaderSize = ethframeclass.ethframe.mHeader.GetSize();
            ethframeclass.ethframe.mHeader.baseheader.HeaderVersion = 1;
            ethframeclass.ethframe.mHeader.baseheader.signature = objectheaderclass.BL_OBJ_SIGNATURE;
            ethframeclass.ethframe.mHeader.baseheader.ObjectType = (ushort)BLF_Function.ObjectHeader.OBJ_TYPR.BL_OBJ_TYPE_ETHERNET_FRAME;
            ethframeclass.ethframe.mHeader.mObjectFlags = (uint)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;

            BLF_Function.VBLAppText appTextclass = new BLF_Function.VBLAppText();
            appTextclass.appText.mHeader=vblobjectheaderclass.mHeader;
            appTextclass.appText.mHeader.baseheader.HeaderSize = appTextclass.appText.mHeader.GetSize();
            appTextclass.appText.mHeader.baseheader.HeaderVersion = 1;
            appTextclass.appText.mHeader.baseheader.signature = objectheaderclass.BL_OBJ_SIGNATURE;
            appTextclass.appText.mHeader.baseheader.ObjectSize = (ushort)appTextclass.GetSize();
            appTextclass.appText.mHeader.baseheader.ObjectType = (ushort)BLF_Function.ObjectHeader.OBJ_TYPR.BL_OBJ_TYPE_APP_TEXT;
            appTextclass.appText.mHeader.mObjectFlags = (uint)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;

            for (int h=0;h<ethbuffer.Length;h++)
                ethbuffer[h]=Convert.ToByte(h & 0xFF);

            for (int i = 0; i < 1000 ; ++i)
            {
                    /* increment in milliseconds */
                    time = (uint)(i * 100000);

                    /* setup app trigger object header */
                    apptriggerclass.apptrigger.mHeader.mObjectTimestamp = time;

                /* write app trigger object */
                success = Scrivi(Handle, apptriggerclass.apptrigger.mHeader.baseheader);////NO ERROR
                written += success ? 1 : 0;
                if (success)
                    {
                    string envdata1="01234567";
                    string envdata2="76543210";
                    /* setup CAN object header */
                     messageclass.message.mHeader.mObjectTimestamp = time;

                        /* setup CAN message */
                        messageclass.message.mChannel=1;
                    messageclass.message.mFlags=(byte)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;
                        messageclass.message.mDLC = 8;
                        messageclass.message.mID = 0x100;
                        char[] supp  = envdata1.ToCharArray();
                    char[] supp2 = envdata2.ToCharArray();
                    messageclass.message.Data = new byte[messageclass.message.mDLC];
                    if ((i%2)==0)
                    {
                        for (int g=0;g<supp.Length;g++)
                        messageclass.message.Data[g] = (byte)supp[g];
                    }
                    else
                    {
                        for (int g=0;g<supp2.Length;g++)
                        messageclass.message.Data[g] = (byte)supp2[g];
                    }

                        /* write CAN message */
                        success = Scrivi(Handle, messageclass.message.mHeader.baseheader);////NO ERROR

                        written += success ? 1 : 0;
                    if (success)
                    {
                    if ((i%3)==0)
                    {
                    /* setup environment variable object headers */
                    variable_sclass.variable_s.mHeader.mObjectTimestamp= time;


                    /* setup environment variables */
                    string envname1="EnvString";
                    string envname2="EnvInt";

                    char[] suppstring1  = envname1.ToCharArray();
                    char[] suppstring2 = envname2.ToCharArray();

                    variable_sclass.variable_s.NameLength = (uint)envname1.Length;
                    variable_sclass.variable_s.DataLength = (uint)(((i%2)==0)?envdata1.Length:envdata2.Length);
                    variable_sclass.variable_s.Name = envname1;

                    variable_sclass.variable_s.Data = new byte[variable_sclass.variable_s.DataLength];
                        if ((i%2)==0)
                        {
                        for (int g=0;g<supp.Length;g++)
                            variable_sclass.variable_s.Data[g] = Convert.ToByte(supp[g]);

                        }
                        else
                        {
                        for (int g=0;g<supp2.Length;g++)
                            variable_sclass.variable_s.Data[g] = Convert.ToByte(supp2[g]);

                        }
                        variable_sclass.variable_s.mHeader.baseheader.ObjectSize = 65;
                        success = Scrivi(Handle, variable_sclass.variable_s.mHeader.baseheader);////ERROR
...........                     
}

public static bool Scrivi(int a, BLF_Function.ObjectHeader.ObjHeader b)
{
return MyBLF.BLWriteObject( a, ref b);
}

CB

2 个答案:

答案 0 :(得分:1)

首先,类型HANDLE应转换为IntPtr,而不是int。

由于结构填充,结构的尺寸也可能与原始尺寸不同。使用C#代码中的[Structlayout()] - 属性来控制它。

答案 1 :(得分:0)

将C#中的“ref”更改为“out”,并查看c ++代码中没有内存分配问题。