首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Delphi DLL 傳遞 DataModule 導致二次調用 Access Violation 的根因與修復

     編輯:程式設計綜合問答

問題現象

主程序調用 DLL 顯示窗體,首次正常;關閉窗體後再次調用,報 Read of address 00000008(Access Violation)。

根本原因

DLL 導出函數 GetForm 和 InitDLL 參數為 TDataModule1 對象指針:

function GetForm(ClassName: PChar; DM: TDataModule1): TFormClass; stdcall;
procedure InitDLL(DM: TDataModule1); stdcall;

跨模塊傳遞 VCL 對象指針是未定義行為:主程序與 DLL 各自擁有獨立的 VCL 運行時、堆管理器、類表。對象內部的虛函數表指針、引用計數在模塊邊界失效,導致二次使用時訪問野指針。

修復方案:傳遞連接字符串而非對象

  1. DLL 導出函數改為接收 ConnectionString: PChar。
  2. DLL 內部自行創建 TADOConnection 並 ConnectionString := ConnectionString。
  3. 主程序調用時傳遞 Frm_DataModule.ADOCNT.ConnectionString。

修正後導出聲明

function GetForm(ClassName, ConnStr: PChar): TFormClass; stdcall;
procedure InitDLL(ConnStr: PChar); stdcall;

補充最佳實踐

  • ShareMem:若必須共享對象,需在專案首部添加 ShareMem 單元(使用 borlndmm.dll),但強烈不推薦,維護成本極高。
  • 包裝為 COM/接口:定義純介面 IDataAccess,DLL 實現並導出工廠函數返回介面,主程序僅持有介面引用,跨模塊安全。
  • 資源管理:DLL 窗體關閉時 Action := caFree,確保釋放;主程序 FreeLibrary 前確保所有 DLL 對象已釋放。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved