2014-09-20 51 views
0

我試圖從一個線程調用一個指針。 這裏是我的代碼:從C++線程調用指針

將myDll.dll C++:

long cbAddrAsync; 
void _asyncer(void* data) 
{ 
     typedef void (__stdcall *FUNCPTR)(); 
    FUNCPTR vbFunc; 
    vbFunc = (FUNCPTR)cbAddrAsync; 
    vbFunc(); 
} 
extern "C" __declspec(dllexport) void async(long addr) 
{ 
    cbAddrAsync = addr; 
    HANDLE hHandle = (HANDLE)_beginthread(_asyncer,0,NULL); 
} 

調用這個EXTERN使用VB6: 在模塊1:

Declare Sub async Lib "myDll.dll" (ByVal addr As Long) 
Sub onAsync() 
MsgBox "ASYNC" 
End Sub 

在Form1:

Private Sub Command_Click() 
Call async(AddressOf Module1.onAsync) 
End Sub 

當我點擊命令按鈕,將出現問題的

dll: 
Unhandled exception at 0x734f9232 in Project1.exe: 0xC0000005: Access violation reading location 0x00000076. 
in vbFunc(); 

我怎樣才能解決呢? 謝謝。

+0

要在問題中正確格式化代碼,只需用至少4個空格縮進代碼行即可。 – 2014-09-20 09:25:29

+1

您需要遠遠超過_beginthread創建一個線程來運行VB代碼。它需要一些稱爲線程本地存儲的東西需要設置,而且你不能訪問任何UI和最常見/共享的數據。即使API調用也需要TLS,除非它們在類型庫中進行了decalred。查看http://hashvb.earlsoft.co.uk/Multi_threading – Deanna 2014-09-23 11:19:23

+0

最簡單的方法是'_asyncer'創建一個公共的VB6創建類的實例。您需要在新線程上使用'CoInitialize'和'CoCreateInstance'傳遞VB6類CLSID。這將初始化VB6運行時(包括TLS等),以便您可以調用您的'AddressOf'回調並在其中使用所有VB6內置函數。 – wqw 2014-09-23 21:32:14

回答

0

0x00000076是無效的內存地址。 0x0000ffff以下的所有地址都是無效的。這沿着0x0和0x0 + 2(或0x0 + 0x76)等線捕獲了一整類錯誤(失敗的內存分配或對象創建)。錯誤是程序員應該檢查但通常不檢查的錯誤。

我的猜測是你正在訪問未初始化的結構的0x76字節。

VB6被設計成一個COM服務器而不是一個動態加載DLL。

AddressOf有規則,因爲你實際上調用VB6運行時而不是你的程序。

您也可以從調試器開始。

windbg或ntsd(ntsd是一個控制檯程序,也許安裝)。兩者都來自Windows調試工具。

下載並安裝Windows調試工具

http://msdn.microsoft.com/en-us/windows/hardware/hh852363

安裝Windows SDK,但只要選擇調試工具。

在C中創建一個名爲Symbols的文件夾:\

Start Windbg。文件菜單 - 符號文件路徑,並進入

srv*C:\symbols*http://msdl.microsoft.com/download/symbols 

然後

windbg -o -g -G c:\windows\system32\cmd.exe /k batfile.bat 

您可以按F12阻止它和kb會顯示調用堆棧(g繼續程序)。如果有錯誤,它也會停止並顯示它們。

類型lm列出加載的模塊,x *!*列出符號和bp symbolname設置在VB6斷點

如果編程那麼這個環境變量link=/pdb:none存儲符號的dll,而不是單獨的文件。請確保您編譯的程序爲無優化並勾選框爲創建符號調試信息。兩者都在編譯選項卡中項目的屬性

另外CoClassSyms(microsoft.com/msj/0399/hood/hood0399.aspx)可以從類型庫中創建符號。