Delphi中TEmployerData调用AddEmployee/AddYear触发访问违规求助
Delphi调用TEmployerData方法触发Access Violation排查
常见排查方向
1. 内部集合未初始化
检查TEmployerData的构造函数,确认是否在实例创建时初始化了ErEesList、ErPayList、ErYears这些内部集合。如果仅声明了集合字段但未在构造函数中创建实例,调用Add类方法时会访问空指针触发AV。
错误示例:
type TEmployerData = class private ErEesList: TObjectList<TEmployee>; public constructor Create; // 未初始化ErEesList procedure AddEmployee(Emp: TEmployee); end; procedure TEmployerData.AddEmployee(Emp: TEmployee); begin ErEesList.Add(Emp); // 空指针访问,触发AV end;
修复方式:在构造函数中初始化所有内部集合,并在析构函数中释放:
constructor TEmployerData.Create; begin inherited; ErEesList := TObjectList<TEmployee>.Create(True); // True表示自动释放元素 ErPayList := TObjectList<TPaySlip>.Create(True); ErYears := TList<Integer>.Create; end; destructor TEmployerData.Destroy; begin ErEesList.Free; ErPayList.Free; ErYears.Free; inherited; end;
2. ErsObjList中的TEmployerData实例为空
检查构建ErsObjList的代码,确保向列表中添加的是已创建的TEmployerData实例。如果仅声明变量但未调用Create就添加到列表,后续调用该实例的方法会触发AV。
错误示例:
var Employer: TEmployerData; begin ErsObjList := TObjectList<TEmployerData>.Create(True); ErsObjList.Add(Employer); // Employer未初始化,指向随机内存 ErsObjList[0].AddEmployee(...); // 触发AV end;
修复方式:添加前必须创建实例:
var Employer: TEmployerData; begin ErsObjList := TObjectList<TEmployerData>.Create(True); Employer := TEmployerData.Create; ErsObjList.Add(Employer); ErsObjList[0].AddEmployee(...); end;
3. 方法调用的目标对象无效
检查调用AddEmployee/AddYear的代码:
- 是否存在索引越界(比如访问
ErsObjList中不存在的元素位置) - 目标实例是否已被提前释放(比如手动调用了
Free但未从ErsObjList中移除)
示例错误场景:
// ErsObjList仅有2个元素,访问索引2会返回空指针 ErsObjList[2].AddEmployee(...); // 手动释放列表元素后,列表中留存野指针 Employer := TEmployerData.Create; ErsObjList.Add(Employer); Employer.Free; ErsObjList[0].AddEmployee(...); // 触发AV
4. 内存管理冲突
如果ErsObjList创建时传入了True(自动管理元素释放),不要手动释放列表中的TEmployerData实例,否则会导致重复释放,后续访问时触发AV。
内容的提问来源于stack exchange,提问作者Bronsi
相关产品推荐
相关产品推荐

