仅当调用第三方DLL时崩溃



我必须使用与特定硬件(巴西税务控制相关硬件(通信的第三方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破坏的内存空间时,它会受到访问侵犯。

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

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

根据这篇文章,这两种调用DLL函数的方法之间的区别仅在于谁负责清理堆栈。当我使用stdcall时,函数负责清理堆栈,而当我使用cdecl时,则由调用方负责。

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

最新更新