2011-06-01 79 views
1

我有從DLL導入的函數。我控制主機可執行文件和動態庫的源代碼。現在,在DLLMain中,我使用MessageBox來彈出正在導出的函數的地址,並使用斷點將其與GetProcAddress返回的函數指針進行比較,它們是相同的。訪問衝突調用導入的函數

但是,當我嘗試調用該函數時,出現訪問衝突。有問題的函數只返回NULL並且沒有邏輯,所以它不能被函數拋出。

如何調用一個已知的有效函數指針,使用正確的簽名和已驗證的安全邏輯產生訪問衝突?

編輯:通過另一個關於調試器在這種情況下死亡的另一個問題獲得的信息表明我的堆棧也被砸了?這比AV更有意義,但函數指針和函數完全兼容,地址是正確的。

extern "C" Render* __cdecl CreateRender(WindowsOS* ptr) { 
    return nullptr; 
} 

typedef Render*(__cdecl *RendererCreateFunction)(WindowsOS*); 

我在DLLMain中使用了一小段簡單的代碼來限定它們實際上與編譯器兼容。

BOOL WINAPI DllMain(
    __in HINSTANCE hinstDLL, 
    __in DWORD fdwReason, 
    __in LPVOID lpvReserved 
) { 
    RendererCreateFunction func = &CreateRender; 
} 

如果它們不兼容(它們包括相同的頭),那麼編譯器應該拋出一個錯誤並拒絕生成DLL,但它接受這個就好了。

+7

也許調用約定不一致? – Vlad 2011-06-01 15:14:36

+0

這是默認調用約定。我在兩側明確指定了__cdecl,在同一個模式(調試|釋放)和一個多線程設置(mt | mtd | etc)下,同一個效果 – Puppy 2011-06-01 15:21:34

+0

都是針對一個架構的一部分組合的? – Raiv 2011-06-01 15:26:07

回答

0

我完全失敗了這一個。寫了一個管理資源的類,但不尊重我的移動並正確地複製語義。事實證明,在我需要使用它之前,我錯誤地在圖書館打電話給FreeLibrary()

1

如果這是你在代碼中使用的DLLMain,那麼它沒有返回語句,很可能返回一個未初始化的值,很可能是0作爲一個很好的主函數,它有效地從內存中卸載DLL。確保DLLMain返回TRUE。

+0

當DllMain返回FALSE時,不應該LoadLibrary失敗? – harper 2011-06-01 16:29:43

+0

是的 - 我不知道爲什麼VS會接受它,沒有回報價值。但是,即使DLLMain返回false,那麼'LoadLibrary'返回NULL,'GetProcAddress'返回NULL。除了我已經對如果DLL加載失敗後會發生什麼保護措施之外,我還驗證了函數指針是由DLL報告的正確地址。 – Puppy 2011-06-01 16:31:24

+0

是的,我承認DLLMain的失敗應該將LoadLibrary中的錯誤鏈接起來,但所描述的調試問題使我認爲DLL以某種方式消失,可能是多線程。 – jszpilewski 2011-06-01 16:48:40