成功返回后,SQLite回调会导致递归异常

时间:2011-11-20 12:58:35

标签: delphi sqlite

我正在使用Zeite组件访问的SQLite数据库版本3.7.9开发这个德里2009应用程序。开始关闭 - 如果不存在,我可以创建一个数据库,创建表并插入记录 - “正常的东西”。有一个小表包含用于连接到某些旧设备的串行参数,并且需要通知串行通信处理程序连接参数更改,但Zeos组件不支持SQLite上的事件。

我查看了SQLite API并且有一个“数据更改通知回调”,所以我着手实现这一点。设置原型是:

void *sqlite3_update_hook(
  sqlite3*, 
  void(*)(void *,int ,char const *,char const *,sqlite3_int64),
  void*
);

所以,在Delphi中,我导入了DLL调用:

function sqlite3_update_hook(pDB:pointer;pCallback:pointer;aux:pointer): pointer; stdcall;
..
function sqlite3_update_hook; external 'sqlite3.dll' name 'sqlite3_update_hook';

..并宣布一个空的回调用于测试:

function DBcallback(aux:pointer;CBtype:integer;CBdatabaseName:PChar;CBtableName:PChar;CBrowID:Int64):pointer; stdcall;
begin

end;

..并调用设置:

sqlite3_update_hook(SQLiteHandle,@DBcallback,dmOilmon);

SQLiteHandle是连接后从驱动程序检索的数据库的sqlite3*指针。 dmOilmon是DataModule实例,因此,当正常工作时,我可以从回调中调用一些方法,(是的,我知道回调是在一个未知的线程中 - 我可以处理那个好,我只是发信号信号灯)。

好消息:当我运行应用程序时,DBcallback在第一次插入时被成功调用。坏消息:一段时间后,该应用程序爆炸了“太多异常”,通常是一个充满'??'的CPU窗口,(偶尔的替代方案是系统死机和重启 - Vista Ultimate 64)。在回调中断,aux,CBtypeCBrowID都是预期的,但调试器工具提示显示CBdatabaseName / CBtableName PChars指向一个字符串汉字..

我试图追踪调用回调的位置 - 由于某种原因,调用链在Zeos驱动程序代码中传递。在那里打破并单步执行,我检查了堆栈指针,它在回调之前和之后都是一样的。

所以,我设置了'空'回调,回调在预期的点被调用但是看起来很狡猾的参数,回调返回到它与SP正确相关的位置。我好像做得对,但...... :((

有没有人见过这个,(或者甚至修好了它?)?

你能建议一种机制,通过这种机制,一个成功的回调可以使应用程序稍后产生递归异常吗?

有没有人有进一步调试的建议?

RGDS, 马丁

1 个答案:

答案 0 :(得分:2)

您在将SQLite标头正确转换为Delphi并使用链接时遇到了问题:

  1. 不是stdcall,但必须是cdecl
  2. 您的function DBcallback必须是procedure。因为void(*)(...)是指向返回void的C函数的指针。
  3. 不是PChar,但必须是PAnsiChar。对于非Unicode Delphi,它可能并不重要,对于Unicode Delphi来说,它只是一个正确的翻译。
  4. 您正在使用编译时动态链接(external 'sqlite3.dll' ...)到sqlite3.dll。但ZeosLib使用运行时动态链接(LoadLibrary& GetProcAddress)。这可能导致“DLL地狱”问题,当你的EXE加载一个sqlite3.dll,ZeosLib计划加载另一个sqlite3.dll。