在Delphi中将记录的指针分配给char数组 - 再来一次?

时间:2011-01-11 11:23:29

标签: delphi

我最近开始研究Delphi项目,发现了一段非常奇怪的代码。

// Type declarations

type
    TDataSet = record
    VolumeLevel : char;
    DeviceMasks : char;
    DeviceList: array [1..MAX] of array [1..8] of char;
    DisplayList: array [1..MAX] of array [1..8] of char;
end;

type
    TSerialPacket = record
    Preamble: array[1..4] of byte;
    PacketType: byte;
    PacketLen: byte;
    Data: array of char;
    Checksum: byte;
end;

...

// Private fields

Packet  : TSerialPacket;
DataSet : TDataSet;

...

// Actual procedure

SetLength(Packet.Data, sizeof(DataSet));
Packet.Data := @DataSet;

我没有非常使用Delphi,所以这段代码对我来说似乎难以理解。编译器认为这没关系,我可以运行代码。我用调试器运行它,但Packet.Data的值似乎没有改变。谁能告诉我这是做什么的?将自定义记录的指针分配给字符数组似乎很奇怪。

此外,由于某种原因,SetLength会触发错误:“Project Foo.exe引发异常类EAccessViolation,并在模块'Foo.exe'中显示地址00403860处的访问冲突。读取地址00000000。”。在工作和崩溃运行期间,Packet.Data的值为(),而Dataof的sizeof为260.我无法确定究竟有什么变化。据我所知,SetLength不应该依赖于Packet.Data和DataSet之外的任何其他变量。

(我在Windows 7上使用Delphi XE。)

2 个答案:

答案 0 :(得分:4)

我猜最后一行(

Packet.Data := @DataSet;

)应该是

Move(DataSet, Packet.Data[0], SizeOf(DataSet));

答案 1 :(得分:1)

我想我知道您的代码出了什么问题......

就像已经说过的那样,这非常糟糕:

SetLength(Packet.Data, sizeof(DataSet)); 
Packet.Data := @DataSet; 

我假设您的代码仅在第二次运行时才会在SetLength上崩溃。 会发生什么

Packet.Data := @DataSet;

这里,Char指针数组被数据集变量的地址替换。然后“释放”由“Setlength”创建的Char数组。

当你第二次进入SetLength时,编译器认为指向Char数组的指针实际上是指向TDataset的指针。它类似于调用

SetLength(@Dataset, SizeOf(Dataset));

(除了编​​译器不允许那个)

我希望这有助于找到您遇到的任何其他问题。