在Delphi中将一个记录指针分配给一个字符数组-再来?
我最近开始做一个Delphi项目,发现了一段非常奇怪的代码在Delphi中将一个记录指针分配给一个字符数组-再来?,delphi,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
// 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。。在工作和崩溃运行期间,数据包的值为,数据集的大小为260。我还没能确定到底发生了什么变化。据我所知,SetLength不应该依赖于Packet.Data和DataSet以外的任何其他变量
我在Windows 7上使用Delphi XE。我猜最后一行是
Packet.Data := @DataSet;
宁可
Move(DataSet, Packet.Data[0], SizeOf(DataSet));
我猜最后一行
Packet.Data := @DataSet;
宁可
Move(DataSet, Packet.Data[0], SizeOf(DataSet));
我想我知道你的代码出了什么问题 如前所述,这相当糟糕:
SetLength(Packet.Data, sizeof(DataSet));
Packet.Data := @DataSet;
我假设你的代码只会在第二次运行SetLength时崩溃。
发生的是
Packet.Data := @DataSet;
这里,Char指针数组被Dataset变量的地址替换。然后释放由Setlength创建的字符数组
当您第二次访问SetLength时,编译器认为指向Char数组的指针实际上是指向TDataset的指针。这类似于打电话
SetLength(@Dataset, SizeOf(Dataset));
只是编译器不允许这样
我希望这有助于发现您遇到的任何其他问题。我想我知道您的代码出了什么问题 如前所述,这相当糟糕:
SetLength(Packet.Data, sizeof(DataSet));
Packet.Data := @DataSet;
我假设你的代码只会在第二次运行SetLength时崩溃。
发生的是
Packet.Data := @DataSet;
这里,Char指针数组被Dataset变量的地址替换。然后释放由Setlength创建的字符数组
当您第二次访问SetLength时,编译器认为指向Char数组的指针实际上是指向TDataset的指针。这类似于打电话
SetLength(@Dataset, SizeOf(Dataset));
只是编译器不允许这样
我希望这有助于发现您遇到的任何其他问题。FWIW:D2007我得到了[DCC Fehler]项目1.dpr35:E2010 InCompatible Typen:“动态数组”和“指针”,正如我快速查看代码所期望的那样。奇怪。对于Packet.Data:=数据集,我遇到了一个错误:类型不兼容:“dynamic array”和TDataSet。但是Packet.Data:=@DataSet是可以的。啊,这是罪过。我已经更改了默认编译器选项,将{$TYPEDADDRESS ON}包括在内,这就解释了区别。但根据您目前的经验,您可能也应该将其包括在内:-是的,我可能应该。一旦软件正常工作,我将打开所有警告级别并修复问题。不幸的是,前几位作者似乎只修复了错误,没有注意到所有的警告。我认识那种开发人员-FWIW:通过D2007,我得到了[DCC Fehler]项目1.dpr35:E2010 InCompatible Typen:“动态数组”和“指针”,正如我快速查看代码所期望的那样。奇怪。对于Packet.Data:=数据集,我遇到了一个错误:类型不兼容:“dynamic array”和TDataSet。但是Packet.Data:=@DataSet是可以的。啊,这是罪过。我已经更改了默认编译器选项,将{$TYPEDADDRESS ON}包括在内,这就解释了区别。但根据您目前的经验,您可能也应该将其包括在内:-是的,我可能应该。一旦软件正常工作,我将打开所有警告级别并修复问题。不幸的是,前几位作者似乎只修复了错误,没有注意到所有的警告。我认识那种开发人员-这两者有什么区别?上面的一个是某种不推荐的方式,还是一直以来都是一个丑陋的黑客行为?AFAICS的指针分配是一个错误。我不相信它能在比您的测试样本稍微复杂的代码中可靠地工作。如上所述,我建议任何人将$TYPEDADDRESS设置为ON。然后编译器会帮你检测到这种错误。虽然这并没有解决我的整个问题,但它为我指明了前进的方向,所以我将它标记为已接受。考虑到上面有限的代码示例,我甚至不知道这个问题是否可以解决。当我解决这个问题时,我会回到这个问题上来。@Ville,你在问题中提到的技术一直都是错误的,而且总是容易出现内存损坏和无效指针操作异常。不管是谁写的代码都没有思考。它设置数组的长度,然后通过为变量指定一个新值来丢弃该数组。新值不是动态数组。它可能看起来有点类似于动态数组,但任何尝试使用它的行为都会导致
ld失败,因为新值不包括真实动态数组所需的动态数组簿记。这两者之间有什么区别?上面的一个是某种不推荐的方式,还是一直以来都是一个丑陋的黑客行为?AFAICS的指针分配是一个错误。我不相信它能在比您的测试样本稍微复杂的代码中可靠地工作。如上所述,我建议任何人将$TYPEDADDRESS设置为ON。然后编译器会帮你检测到这种错误。虽然这并没有解决我的整个问题,但它为我指明了前进的方向,所以我将它标记为已接受。考虑到上面有限的代码示例,我甚至不知道这个问题是否可以解决。当我解决这个问题时,我会回到这个问题上来。@Ville,你在问题中提到的技术一直都是错误的,而且总是容易出现内存损坏和无效指针操作异常。不管是谁写的代码都没有思考。它设置数组的长度,然后通过为变量指定一个新值来丢弃该数组。新值不是动态数组。它可能看起来有点类似于动态数组,但任何尝试使用它的尝试都可能失败,因为新值不包括真实动态数组所需的动态数组簿记。这解决了问题,所以我接受这个而不是Ulrich的答案。这解决了问题,所以我接受这个而不是Ulrich的答案。