Unhandled Exception: System.AccessViolationExcepti

2019-06-01 02:58发布

问题:

Below is my c++ DLL

// DLL.cpp : Defines the exported functions for the DLL application.
#include "stdafx.h"
//#include <stdexcept> 
#include<iostream>
using namespace std; 

typedef void (*FunctionPtr)(int); 
void (*FunctionPtr1)(int); 
extern "C" __declspec(dllexport)void Caller();
extern "C" __declspec(dllexport)void RegisterFunction(FunctionPtr func_ptr); 


    extern void Caller() 
    {    

        int i = 10;
        FunctionPtr1(i);
 } 

    extern void RegisterFunction(FunctionPtr func_ptr1)
 {
     FunctionPtr1 = func_ptr1;

 }

This DLL will get refernce to function name from c# and pass arguments to c# function.. here is my c# code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;



namespace test
{
    class Program
    {

        [DllImport("C:/Users/10602857/Documents/Visual Studio 2010/Projects/DLL/Debug/DLL.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void Caller();

       [DllImport("C:/Users/10602857/Documents/Visual Studio 2010/Projects/DLL/Debug/DLL.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern fPointer  RegisterFunction(fPointer aa);

        static void Main(string[] args)
            {
                    Console.WriteLine("DLL Linking");
                    fPointer abc = new fPointer(ping);
                    RegisterFunction(abc);      //send address of function to DLL
                    Caller();                   //call from DLL
            }

        public  delegate void fPointer(int s);       // point to every functions that it has void as return value and with no input parameter 


        public static void ping(int a)
             {
                     Console.WriteLine("ping executed " + a);
             }

        public static void add1()
              {
                      Console.WriteLine("add executed");
              }

    }
}

c# code is able to get the value which i paseed in c++ dll as below

int i = 10;
        FunctionPtr1(i);

M getting the sedired output but progrram got crashed at the end with following execption

Unhandled Exception: System.AccessViolationException: Attempted to read or write
 protected memory. This is often an indication that other memory is corrupt.
   at test.Program.Caller()

why i am getting this ??

回答1:

Okay, I wrote test code for you. Concept is simple.

  1. You wrote dll using C++ or C.

  2. CLR library(Managed dll) wraps your dll.

  3. Your C# code can use your Native DLL via CLR library.

Your Native DLL

MyDll.cpp

#include "stdafx.h"

#include<iostream>
using namespace std; 

typedef void (*FunctionPtr)(int); 
void (*FunctionPtr1)(int); 
extern "C" __declspec(dllexport)void Caller();
extern "C" __declspec(dllexport)void RegisterFunction(FunctionPtr func_ptr); 


extern void Caller() 
{    
    int i = 10;
    FunctionPtr1(i);
} 

extern void RegisterFunction(FunctionPtr func_ptr1)
{
    FunctionPtr1 = func_ptr1;
}

Your CLR library, wrapper for Native Dll

MyDllCLR.h

#pragma once

using namespace System;
using namespace System::Runtime::InteropServices;

typedef void (*FunctionPtr2)(int); 
extern "C" __declspec(dllimport)void Caller();
extern "C" __declspec(dllimport)void RegisterFunction(FunctionPtr2 func_ptr); 

namespace MyDllCLR {

    void MyFunc(int i);

    public ref class Class
    {        
    public:
        delegate void FunctionDelegate(int i);
        static FunctionDelegate^ fun;

        static void Caller1()
        {
            Caller();
        }

        static void RegisterFunction1(FunctionDelegate^ f)
        {
            fun = f; // Wrapper MyFunc call this delegate

            // this occurs runtime error and I don't know why.
            // So I wrote Warpper MyFunc() method. I usually do like this.
            //IntPtr p = Marshal::GetFunctionPointerForDelegate(fun);
            //RegisterFunction((FunctionPtr2)(void*)p);

            // Register Function Wrapper instead of user delegate.
            RegisterFunction(MyFunc);
        }
    };    
}

MyDllCLR.cpp

#include "stdafx.h"
#include "MyDllCLR.h"

void MyDllCLR::MyFunc(int i)
{
    MyDllCLR::Class::fun(i);
}

Your C# code using Native DLL

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestMyDllCLR
{
    class Program
    {
        static void MyFunc(int i)
        {
            Console.WriteLine("Come on! {0}", i);
        }

        static void Main(string[] args)
        {
            MyDllCLR.Class.RegisterFunction1(MyFunc);
            MyDllCLR.Class.Caller1();
        }
    }
}

You need Native DLL and CLR DLL both for Program.cs

And, of course, this is not the only way for your goal. :)



回答2:

It could well be that your delegate

fPointer abc = new fPointer(ping);

is getting garbage collected before it's being used. You need to store the reference to the delegate as a field of the class to ensure it survives for the lifetime of the class.

Try defining fPointer abc outside main then assign new fPointer(ping) to it inside main and see if that helps.



回答3:

All i need to do is.. just declare my delegate as ...

[UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
public delegate void MyDelegate();