Class delphi类中的访问冲突
我有一门课是这样的:Class delphi类中的访问冲突,class,delphi,delphi-7,access-violation,Class,Delphi,Delphi 7,Access Violation,我有一门课是这样的: Component = class(TObject) Name: string; CurState: word; States: array of state; constructor Create(nm: string); procedure AddState(ccl: bool; const InB: BufArr; const OutB: BufArr); function Ge
Component = class(TObject)
Name: string;
CurState: word;
States: array of state;
constructor Create(nm: string);
procedure AddState(ccl: bool; const InB: BufArr; const OutB: BufArr);
function GetStateCount(): Integer;
end;
States
是一个state
数组,也是一个类声明
State = class(TObject)
InBuf: BufArr;
OutBuf: BufArr;
Cycle: bool;
constructor Create(ccl: bool; const InB: BufArr; const OutB: BufArr);
end;
每个组件
可以包含多个状态
,这就是为什么我有一个状态
数组的原因
函数应返回组件的状态数。实现如下:
function Component.GetStateCount(): Integer;
begin
result:=Length(States);
end;
但是,当我在另一个过程中调用此函数时,会出现以下错误:
我似乎想不出这件事的原因。谢谢你的帮助
好的,下面是我调用函数的代码部分:
for i:=0 to nc-1 do
begin
cycle:=false;
len:=cmp[i].GetStateCount;
for j:=0 to len-1 do
if not cmp[i].States[j].Cycle or cycle then
continue;
cycle:=true;
for k:= 0 to length(cmp[i].States[j].InBuf)-1 do
begin
m:=cmp[i].States[j].InBuf[k];
if m>0 then
graph[m-1,i]:= graph[m-1,i]+1;
end;
end;
读取地址0000000 xx
-注意,引用的地址几乎为零,但略高于该地址-表明您在尝试访问其内部字段(在该函数的调用中)时未创建对象
要测试该假设,请以“防御性编程”的方式重写函数:
如果抛出了自定义异常,那么就是它,您应该调试为什么没有创建组件
components对象的字段变量正在从Self
指针的值偏移。对于Win32程序,它们通常是内存对齐的
到4字节(32位)的边界
我们本来是这样的
- Self+0==>指向VMT(虚拟方法表)的指针
- Self+4==>
//指向Component.Name
TStringRec的指针
- Self+8==>
//使用两个字节,两个字节“填充”组件。CurState
- Self+12==>
//指向dyn数组帧的指针组件。状态
(Self=nil)
时为(0+12)
注意:在Delphi7中,一些格式是不同的,例如长字符串没有代码页字段
在问题的代码中,
cmp[i]
有时是nil
——您必须确定这是否是有效的情况
如果它是有效的,您必须在循环中检查它
for i:=0 to nc-1 do
begin
if nil = cmp[I] then continue;
cycle:=false;
...
如果数组中不应有nil
元素,则必须确定这是如何发生的
for i:=0 to nc-1 do
begin
if nil = cmp[i] then raise Exception.Create(....);
cycle:=false;
...
然而,我相信这是另一项研究的重点(可能是一个问题)。在这里,你问为什么在特定的函数中会有AV,我认为你必须检查Self is nil
假设作为直接原因
另外-在循环体中重复使用cmp[i]
对我来说并不合适。
我建议您将该值缓存到一个局部变量中,您将为此创建一个局部变量
for i:=0 to nc-1 do
begin
curr_cmp := cmp[i];
if nil = curr_cmp then raise Exception.Create(....);
cycle := false;
len := curr_cmp.GetStateCount;
for j:=0 to len-1 do
if not curr_cmp.States[j].Cycle or cycle then
...
这将使编辑和理解代码更容易。如果明天您将该代码移动到一个单独的过程中,或者决定从不同于cmp[i]
的源获取对象,您只需要更改一行,而不是搜索所有可能丢失一两行的cmp[i]
事件。我记得有一次我不得不将索引变量从直接循环更改为更复杂的间接模式,实际上我不得不开始使用两个索引变量,然后延迟复制粘贴cmp[I]
让我觉得很讨厌
另外,这可能会使代码速度稍微加快。
读取地址0000000 xx
-注意,引用的地址几乎为零,但略高于它-表明您在尝试访问其内部字段(在该函数的调用中)时未创建对象
要测试该假设,请以“防御性编程”的方式重写函数:
如果抛出了自定义异常,那么就是它,您应该调试为什么没有创建组件
components对象的字段变量正在从Self
指针的值偏移。对于Win32程序,它们通常是内存对齐的
到4字节(32位)的边界
我们本来是这样的
- Self+0==>指向VMT(虚拟方法表)的指针
- Self+4==>
//指向Component.Name
TStringRec的指针
- Self+8==>
//使用两个字节,两个字节“填充”组件。CurState
- Self+12==>
//指向dyn数组帧的指针组件。状态
(Self=nil)
时为(0+12)
注意:在Delphi7中,一些格式是不同的,例如长字符串没有代码页字段
在问题的代码中,
cmp[i]
有时是nil
——您必须确定这是否是有效的情况
如果它是有效的,您必须在循环中检查它
for i:=0 to nc-1 do
begin
if nil = cmp[I] then continue;
cycle:=false;
...
如果数组中不应有nil
元素,则必须确定这是如何发生的
for i:=0 to nc-1 do
begin
if nil = cmp[i] then raise Exception.Create(....);
cycle:=false;
...
然而,我相信这是另一项研究的重点(可能是一个问题)。在这里,你问为什么在特定的函数中会有AV,我认为你必须检查Self is nil
假设作为直接原因
另外-在循环体中重复使用cmp[i]
对我来说并不合适。
我建议您将该值缓存到一个局部变量中,您将为此创建一个局部变量
for i:=0 to nc-1 do
begin
curr_cmp := cmp[i];
if nil = curr_cmp then raise Exception.Create(....);
cycle := false;
len := curr_cmp.GetStateCount;
for j:=0 to len-1 do
if not curr_cmp.States[j].Cycle or cycle then
...
这将使编辑和理解代码更容易。如果明天您将该代码移动到一个单独的过程中,或者决定从不同于cmp[i]
的源获取对象,您只需要更改一行,而不是搜索所有可能丢失一两行的cmp[i]
事件。我记得有一次我不得不将索引变量从直接循环更改为更复杂的间接模式,实际上我不得不开始使用两个索引变量,然后延迟复制粘贴cmp[I]
让我觉得很讨厌
作为奖励