You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用DLL函数触发Access Violation异常的排查与解决求助

解决DLL中SHA256哈希函数交替触发Access Violation的问题

兄弟,我看了你的问题,这种交替出现的Access Violation在Delphi的DLL和主程序交互时太常见了,根本原因就是跨模块的内存管理不兼容。先把你的代码贴出来方便分析:

DLL中的函数代码

function PedirContraseña() : string; 
var clave, claveCodificada : string; 
begin 
  clave := InputBox('Autenticación', 'Introduzca la clave de acceso', ''); 
  claveCodificada := SHA256Hash(clave); 
  Result := claveCodificada; 
end; 
exports PedirContraseña; 

主应用调用代码

function PedirContraseña() : string; external 'seguridad.dll'; 

procedure Tmenubodega.BitBtn1Click(Sender: TObject); 
var s : string; 
begin 
  inherited; 
  s := PedirContraseña; 
  ShowMessage(s); 
end; 

问题根源

Delphi里的string是引用计数的动态字符串,它的内存分配和释放完全依赖当前模块的内存管理器。如果你的DLL和主程序没有使用共享的内存管理器,DLL中分配的字符串内存,主程序在释放时会用自己的内存管理器去操作不属于它的内存块,直接触发Access Violation。而前两次正常、后面交替异常的情况,是因为内存错误的触发有随机性,前两次内存还没被错误覆盖,第三次开始引用计数的矛盾就显现出来了。

解决方案

最稳妥的两种解决方式:

方案1:使用共享内存管理器(最简单)

在DLL和主程序的uses列表最开头加入ShareMem单元——它会让两个模块共用同一个内存管理器,字符串的分配和释放就能跨模块正常工作。

  • DLL代码修改:
library seguridad;

uses
  ShareMem, // 必须放在第一个位置
  SysUtils, Forms, Dialogs, 你的SHA256相关单元;

// 你的PedirContraseña函数代码...
  • 主程序代码修改:
program 你的主程序名;

uses
  ShareMem, // 同样放在第一个位置
  Vcl.Forms,
  你的主窗体单元;

// 主程序剩余代码...

方案2:改用PChar手动管理内存(适合不能用ShareMem的场景)

如果因为某些限制不能用共享内存管理器,那可以改用PChar传递字符串,手动控制内存分配:

  • DLL函数修改:
function PedirContraseña(out Buffer: PChar; BufferSize: Integer): Integer; stdcall;
var
  clave, claveCodificada: string;
begin
  clave := InputBox('Autenticación', 'Introduzca la clave de acceso', '');
  claveCodificada := SHA256Hash(clave);
  Result := Length(claveCodificada);
  if BufferSize >= Result + 1 then // 要留位置存字符串结束符
    StrPCopy(Buffer, claveCodificada);
end;
exports PedirContraseña;
  • 主程序调用代码修改:
function PedirContraseña(out Buffer: PChar; BufferSize: Integer): Integer; stdcall; external 'seguridad.dll';

procedure Tmenubodega.BitBtn1Click(Sender: TObject);
var
  s: string;
  buf: array[0..63] of Char; // SHA256哈希固定是64字符,数组大小足够
  len: Integer;
begin
  inherited;
  len := PedirContraseña(buf, SizeOf(buf));
  SetString(s, buf, len);
  ShowMessage(s);
end;

注意事项

  • 方案1中ShareMem必须放在uses的第一个位置,这样它才能优先初始化共享内存管理器。
  • 如果你的SHA256哈希函数内部也有内存分配逻辑,要确保它的内存管理和当前模块一致,不过大部分第三方哈希库都会处理好这个问题。

内容的提问来源于stack exchange,提问作者davidrgh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:34:16