2014-01-29 33 views
1

我從cpp項目創建了一個dll。 從vb項目調用該dll時,應用程序崩潰。 與此錯誤消息:從vb調用C++ dll時出現「new」崩潰

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. 

我可以調試DLL,並看到飛機墜毀在這一行

carEngine = new CAREngine(); 

的CAREngine構造是空的。什麼可能導致這次崩潰?

下面的代碼:

C++ h文件:

#include "CarEngine.h" 

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

C++ cpp文件:

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

VB:

<DllImport("myengine.dll", EntryPoint:="?  
    [email protected]@@[email protected]")> _ 
    Public Function initEngine(ByVal lpString As String) As Boolean 
    End Function 

    ... 

    initEngine("C:\1.txt") 
+0

正如我寫的 - CAREngine的構造函數爲空 – iRadium

+0

你能展示更多的VB代碼嗎?就像你如何創建'Engine'實例一樣?或者你只是調用'initEngine'成員函數而沒有任何'Engine'實例? –

+0

這是所有的vb代碼。在VB中沒有引擎類 – iRadium

回答

4

initEngine是實例方法,但是您將其視爲獨立方法。

當您調用實例方法時,theres是一個隱含參數,其值爲this,並且是.->左側變量的地址。但是,您尚未創建Engine的實例,您剛纔稱爲成員函數。您傳入的字符串將用作this的值,lpString參數將最終成爲堆棧中的某個隨機值。

的代碼將在分配到崩潰,因爲carEngine編譯器實際上是將其視爲this->carEngine,並作爲this點的東西,是不是Engine就會失敗。另外,出口C++成員函數以便在C#中使用是很困難的,正如你發現的那樣!您必須鏈接受損的名稱,並且修改可以從編譯器版本更改爲編譯器版本。

如果您確實需要使用C++,則可能需要考慮使用託管C++。另一種方法是公開暴露包含成員函數的C函數並獲取一個不透明的值,該值實際上是指向它們所在實例的指針。例如

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

我不想劫持這個問題,但是(我的C++技能不是最好的)爲什麼傳遞的字符串會被用作'this'的值?我明白沒有'initEngine'的實例可以使用,但爲什麼會嘗試使用函數的第一個參數? – Brandon

+1

所有非靜態成員函數都需要'this'的值。在引擎蓋下,這通常作爲第一個參數傳入。因此'initEngine'被編譯器視爲'initEngine(Engine * this,LPCTSTR DBFilename)'。你已經告訴VB編譯器第一個參數是一個字符串,但是從C++編譯器的角度來看,第一個參數是一個指向'Engine'實例的指針。 – Sean

+1

我明白了。所以在沒有'this - > ...'的情況下,第一個參數將始終被視爲'(yourType * this ...)'。很好的答案。 – Brandon