仅在调用第三方DLL时崩溃

时间:2018-07-26 19:52:01

标签: delphi dll access-violation delphi-10-seattle

我必须使用与特定硬件(与巴西税控相关的硬件)进行通信的第三方DLL。

此DLL中公开的功能由政府标准化,并由硬件供应商实施。我们的软件已经可以与几个供应商的DLL进行通信,但是对于这个特定的供应商来说,事情变得很奇怪。

好吧,正如您在下面看到的,我已经隔离了有问题的代码:

...
function ConsultarSAT(numeroSessao : Longint ) : PAnsiChar ; stdcall; external 'sat.dll';
...

procedure TForm1.Button1Click(Sender: TObject);
begin
  ConsultarSAT(GetTickCount);
  ShowMessage('Will it crash?');
end;

如果内置发布版本,此代码将崩溃,如果内置调试配置,则将失败。。放置ShowMessage是为了清楚地表明崩溃将在过程结束时发生,而不是在调用“ ConsultarSAT”时发生

通过崩溃我的意思是:

Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 009E591C. Write of address 00000001'.

所以我开始怀疑优化和调试符号。然后我尝试了:

  • 启用优化的调试配置:无崩溃
  • 发布配置(优化关闭):仍然崩溃
  • 使用所有编译器调试配置->调试选项关闭:无崩溃
  • 使用所有编译器发布配置->调试选项打开:仍然崩溃

如果我运行上面的代码,该代码仅从函数中获取返回值并将其显示在showMessage上,则我仍然遇到相同的崩溃情况,但是我能够验证该函数返回了正确的值。

我想这个问题与内存中DLL造成的某种混乱有关,因此它可以正常运行,但是当它返回并且我的应用尝试访问DLL所困扰的某些内存空间时,就会出现访问冲突。 / p>

我还应该寻找什么来了解这里发生的情况?

1 个答案:

答案 0 :(得分:0)

问题是我声明DLL函数的方式。我使用的是stdcall,必须使用cdecl调用此供应商的DLL。

根据this post,这两种调用DLL函数的方式之间的区别仅在于谁负责清理堆栈。当我使用stdcall时,函数的责任是清理堆栈,而当我使用cdecl时,则是调用者的责任。

我对此的知识非常有限,但是我想这种行为可以解释我在这里遇到的所有奇怪问题。问题本身已经解决并经过了深入的测试,但是如果有一个比我更深入的知识的人可以更深入地解答问题,那么其他有类似问题的人可以比我深入研究这个问题的时间更少。