3

我有下一个代码:

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 成员的值对我来说没有意义。我想知道这段代码在某些情况下是否会引发异常,如果是这样,在什么情况下?

4

2 回答 2

6

我猜如果你小心处理它是完全安全的。但是您需要确定您不会忘记您可能无法访问zb11..zb15. 此外,回想一下,achar在 Delphi 2009 之前是 1 个字节,在 Delphi 2009 和更高版本中是 2 个字节。此外,也许值得记录一下packed(在这种情况下你不需要这样做,但迂腐明确永远不会错)?最后,当然你必须小心,以免数组超出范围!

于 2012-04-09T08:55:35.567 回答
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;
于 2012-04-09T17:15:51.940 回答