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

Delphi 10.4 Update2中长波斯语字段调用TClientDataSet.Locate()触发访问冲突

问题原因分析与解决建议

问题重现

  • 环境:Delphi 10.4 Update 2,采用ADOQuery->DataSetProvider->TClientDataSet架构
  • 场景:查询包含25字符全波斯语名称的字段,调用Locate()方法时触发Access Violation
  • 测试SQL:
select 123 as 'تست تست تست تست تست'
union all
select 123 as 'تست تست تست تست تست'
union all
select 123 as 'تست تست تست تست تست'
  • 现象:字段名缩短至16字符时,问题完全消失

核心原因

这是Delphi 10.4.2中TClientDataSet组件处理Unicode长字段名时的内存缓冲区越界问题:

  • 波斯语字符属于UTF-16编码的Unicode字符,每个字符占用2字节。25个波斯语字符对应的字节数为50字节,而16个字符仅对应32字节。
  • TClientDataSet内部在存储、解析字段名,或执行Locate()时的字段匹配逻辑中,使用了固定大小的缓冲区。该缓冲区的设计未充分考虑Unicode字符的字节长度,当字段名字节数超过阈值时,会触发内存访问越界,进而导致Access Violation。
  • 数据从ADOQuery经DataSetProvider传递到TClientDataSet的过程中,字段名的Unicode编码处理存在疏漏,长字段名未被正确适配内部缓冲区,最终引发内存错误。

临时解决办法

  • 缩短字段名:直接将波斯语字段名控制在16字符以内(对应32字节),从根源避免触发缓冲区越界。
  • 手动修改字段名:在DataSetProvider的BeforeGetDataSet事件中,提前修改ADOQuery返回的字段名,缩短至安全长度后再传递给TClientDataSet,示例代码:
procedure TForm1.DataSetProvider1BeforeGetDataSet(Sender: TObject;
  DataSet: TDataSet);
begin
  // 将长字段名替换为短名称
  DataSet.FieldByName('تست تست تست تست تست').FieldName := 'TestShort';
end;
  • 升级Delphi版本:该内存越界问题属于组件已知缺陷,后续Delphi版本(如11.x及以上)已修复此类Unicode字段名的处理逻辑,升级后可彻底解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 10:20:08