Delphi7自定义DBEdit组件设计期添加到窗体触发访问冲突异常
报错根因
Read of address 000000D2是Delphi开发中典型的nil对象偏移访问错误:nil指针值为0,当代码尝试访问类实例偏移0xD2位置的成员时,最终访问地址就是0 + 0xD2 = 0x000000D2,和报错完全匹配。
触发链路:
- 设计期拖入组件时,会先执行构造函数,父类
TDBEdit的构造函数初始化文本状态时会触发Change虚拟方法 - 此时组件还未绑定任何
DataSource、也未打开对应数据集,TDBEdit的Field属性为nil - 重写代码中,
Change方法直接执行if Field.Text<>''的判断,相当于读取nil对象的成员,直接触发访问违规。
修复方案
所有访问Field成员的位置,必须先做空校验,避免设计期/运行期未绑定字段时的空引用。
- 重写
DoFull函数,先判断Field有效性:
function TPrefEdDb.DoFull: string; var s: string; begin Result := ''; // 先校验字段对象存在,未绑定直接返回 if not Assigned(Field) then Exit; // 处理空值判断,替代原来的Field.Value<>null逻辑 if Field.IsNull then Exit; s := Field.Text; if FPre <> '' then s := FPre + s; if FSuff <> '' then s := s + FSuff; Result := s; end;
- 修改
Change方法,增加空判断:
procedure TPrefEdDb.Change; begin inherited Change; // 字段有效时才执行拼接 if Assigned(Field) and (Field.Text <> '') then Full := DoFull; end;
- 清理冗余代码:
KeyPress过程中定义的TabKey、EnterKey常量未被使用,可以直接删除- 重复声明的published事件属性(
OnChange/OnClick等)可以移除,这些事件父类本身就是published状态,重复声明无额外作用,还可能引发属性编辑器异常
- (可选)优化属性设置逻辑,修改
Pre/Suff时自动同步拼接值:
procedure TPrefEdDb.SetPre(Value: string); begin if FPre = Value then Exit; FPre := Value; // 仅在运行期执行拼接,避免设计期空引用 if not (csDesigning in ComponentState) then Full := DoFull; end; procedure TPrefEdDb.SetSuff(Value: string); begin if FSuff = Value then Exit; FSuff := Value; if not (csDesigning in ComponentState) then Full := DoFull; end;
内容的提问来源于stack exchange,提问作者Learning
相关产品推荐
相关产品推荐

