gpt4 book ai didi

delphi - 如何将指针转换回字节数组(或流)?

转载 作者:行者123 更新时间:2023-12-03 18:01:07 24 4
gpt4 key购买 nike

我有一个函数可以创建指向流中数据的指针。

function StreamToByteArray(Stream: TStream): Pointer;
var
ByteArr: array of Byte;
begin
if Assigned(Stream) then
begin
Stream.Position := 0;
SetLength(ByteArr, Stream.Size);
Stream.Read(ByteArr[0], Stream.Size);
end
else
SetLength(ByteArr, 0);
result := @ByteArr[0];
end;

如何将它从指针转换回动态字节数组和
然后将内容保存到流中。或者也许可以直接从
指针?

感谢帮助。

最佳答案

哎呀,这段代码(不幸的是)非常糟糕。您的函数返回一个指向 ByteArr 数组的指针,但不幸的是,当函数存在时该数组超出范围:您实际上返回的是一个无效指针!即使错误没有立即弹出,你也有潜在的访问冲突。

更长的解释

一个 Pointer是一个危险的结构:它不包含数据,它只是说明数据存在的位置。您的无类型 Pointer 示例是最难的一种指针,它没有说明给定地址中存在的数据。它可能指向您从流中读取的某些字节,可能指向字符串甚至某种图片。您甚至无法知道给定地址的数据量。

指针概念与分配内存的概念密切相关。我们使用许多不同的技术来分配内存,使用局部变量、全局变量、对象、动态数组等。在您的示例函数中,您使用的是动态数组,array of Byte .编译器很好地保护了您免受内存分配和重新分配的内部影响,您可以简单地使用 SetLength()说阵列应该有多大。因为动态数组是 Delphi 中的托管数据结构,所以一切都很好:编译器会跟踪您如何使用动态数组,并在不再需要动态数组时立即释放相关的内存。就编译器而言,当您的函数存在时,不再需要关联的内存。

当你在做:

Result := @ByteArr[0];

您实际上是在获取编译器分配的内存块的地址。由于您使用的是非常低级的结构( Pointer ),编译器不可能跟踪您的内存使用情况,因此它会在函数存在时释放内存。这给你留下了一个指向未分配内存的指针。

如何正确返回 Pointer从一个函数

首先,如果可能,您应该避免使用指针:它们是低级的,编译器无法提供类型安全或释放,它们太容易出错。而且,当您确实弄错了指针时,这些错误通常是访问冲突,并且很难跟踪。

也就是说,如果你真的想返回一个指针,你应该返回一个指向显式分配内存的指针,这样你就知道编译器不会为你释放它。当你这样做时,确保接收代码知道它负责内存(应该在不再需要内存时释放内存)。例如,您的函数可以这样重写:
function StreamToByteArray(Stream: TStream): Pointer;
begin
if Assigned(Stream) then
begin
Result := AllocMem(Stream.Size);
Stream.Position := 0;
Stream.Read(Result^, Stream.Size);
end
else
Result := nil;
end;

如何将指针改回 array of byteTStream
答案是,没有办法把它改回来。指针就是这样,指向一些随机数据的指针。一个字节数组比它包含的数据多。一个 TStream更抽象:它是一个告诉您如何检索数据的接口(interface),它不一定包含任何数据。例如, TFileStream (那是 TStream )不包含任何数据字节:所有数据都在磁盘上的文件中。

关于delphi - 如何将指针转换回字节数组(或流)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9309389/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com