我最近开始研究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。)
答案 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));
(除了编译器不允许那个)
我希望这有助于找到您遇到的任何其他问题。