iRadium
iRadium

Reputation: 255

crash on "new" when calling a c++ dll from vb

I'm creating a dll from a cpp project. When calling this dll from a vb project, the app crashes. with this error message:

    An unhandled exception of type 'System.AccessViolationException' occurred in...
    Additional information: Attempted to read or write protected memory. This is often 
    an indication that other memory is corrupt.

I can debug the dll, and see that the crash is in this line

    carEngine = new CAREngine ();

The CAREngine constructor is empty. What could cause this crash?

Here's the code:

C++ .h file:

    #include "CarEngine.h"

    class Engine
    {
    public:
        bool __declspec(dllexport) initEngine(LPCTSTR DBfileName);
    private:
        CAREngine* carEngine;
    };

C++ .cpp file:

    bool Engine::initEngine(LPCTSTR DBfileName)
    {
        logText("Engine Loading start");
        carEngine = new CAREngine ();  //<- Crash is here
        ...
    }

VB:

    <DllImport("myengine.dll", EntryPoint:="?    
    initEngine@Engine@@QAE_NPBD@Z")> _
    Public Function initEngine(ByVal lpString As String) As Boolean
    End Function

    ...

    initEngine("C:\1.txt")

Upvotes: 1

Views: 379

Answers (1)

Sean
Sean

Reputation: 62472

initEngine is an instance method, but you're treating it as a standalone method.

When you call an instance method theres is an implicit parameter that holds the value of this, and is the address of the variable on the left side of the . or ->. However, you have not create an instance of Engine, you've just called a member function. The string you're passing in will be used as the value of the this and the lpString parameter will end up being some random value that's on the stack.

The code will crash on assignment to carEngine because the compiler actually treats it as this->carEngine, and as this points to something that isn't a Engine it will fail.

As an aside, exporting C++ member functions for use in C# is hard work, as you've found out! You have to link by the mangled name, and the mangling can change from compiler version to compiler version.

If you really need to use C++ when you might want to consider using managed C++. Alternativly it's common to expose C functions that wrap the member functions and take an opaque value which is actually a pointer to the instance they operate on. For example

void *EngineCreate();
void EngineInitialize(void *engine)
void EngineSetName(void *engine, const TCHAR *name)
// etc
// etc

Upvotes: 4

Related Questions