我有下一个代码:
type THead = packed record
znmpc: byte;
znmpcch: array [0..1] of char;
znc, zneispr, zkpd, zkps, nd: byte;
zb9, zb10, zb11, zb12, zb13, zb14, zb15: byte;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
db: ^THead;
a: array [0..9] of byte;
begin
a[7] := 9;
db := @a;
ShowMessage(IntToStr(db.nd));
end;
这段代码安全吗?我担心接下来的事情:结构的大小超过缓冲区的大小,我担心它。 nd之后struct的成员值对我没有意义。我想知道这段代码可以在某些情况下抛出异常,如果是这样的话吗?
答案 0 :(得分:6)
如果你仔细处理,我猜它是绝对安全的。但您需要确保不要忘记您可能无法访问zb11..zb15
。此外,回想一下,char
在Delphi 2009之前是1个字节,在Delphi 2009和更高版本中是2个字节。此外,也许值得制作记录packed
(在这种情况下不要认为你需要那个,但是迂腐显然从来都不错)?最后,当然你必须小心,以便数组不会超出范围!
答案 1 :(得分:2)
我想读db.nd很好。您将访问不属于您的堆栈中的某个位置。但是对这个变量写一些东西会导致灾难性的失败,我们无法知道。
另外,如果你的边界过多,你也可能会因为阅读而违反访问权限:
procedure TForm2.Button1Click(Sender: TObject);
var
db: THead;
p: PByte;
begin
db.nd := 9;
p := @db;
ShowMessage(IntToStr(p[7])); // shows 9
ShowMessage(IntToStr(p[700])); // shows 182 for me?
ShowMessage(IntToStr(p[70000])); // shows 0
ShowMessage(IntToStr(p[700000])); // access violation!
end;
使用工会更安全:
type
THead = packed record
znmpc: byte;
znmpcch: array [0..1] of AnsiChar;
znc, zneispr, zkpd, zkps, nd: byte;
zb9, zb10, zb11, zb12, zb13, zb14, zb15: byte;
end;
THeaderUnion = packed record
case Integer of
0: (Head: THead);
1: (ByteArray: Array[0.. sizeof(THead)-1] of Byte);
end;
procedure TForm1.Button1Click(Sender: TObject);
Var
db: THeaderUnion;
begin
db.ByteArray[7] := 9;
ShowMessage(IntToStr(db.Head.nd));
end;