Reputation: 255
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
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