首页 文章

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

提问于
浏览
1

我最近开始研究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 回答

  • 4

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

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

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

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

    Packet.Data := @DataSet;
    

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

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

    SetLength(@Dataset, SizeOf(Dataset));
    

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

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

  • 1

    我猜最后一行(

    Packet.Data := @DataSet;
    

    )应该是

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

相关问题