把一个指针分配为一种类型,然后将其作为另一种类型但大小相同的指针处理,这样做是否可行?

5

分配一个指向某种类型的指针,然后将其释放为同一大小但不同类型的指针,这样做是否可行?我的意思是像这样:

procedure TForm1.Button1Click(Sender: TObject);
var A:PInt64;   // 64bit
    P:Pointer;
    B:PDouble;  // 64bit
begin
  New(A);
  P:=A;
  B:=P;
  Dispose(B);
end;

假设我只需要支持8、16、32、64位有符号和无符号类型,这样可以吗?


2
如何编写难以维护的代码的典型案例! - MartynA
1
无论代码是否易于维护,我只想知道它是否能正常工作,以及是否分配和释放了相同的内存位置……我真的需要这样做。 - Marus Gradinaru
1
@MarusNebunu -- 是的,这里没有内存泄漏。顺便问一下,你是否使用 ReportMemoryLeaksOnShutdown := True; ? - Zam
2
我想看到它的真实用途。它指向了一些可疑的东西。不过这是一个有趣的问题。 - TLama
1
这将起作用,因为内存管理器知道它必须释放的大小,并且由于这些不是托管类型,因此不需要额外的终结。对于托管类型(即需要运行时代码进行额外初始化或终结的类型),它将无法正常工作。因此,通常我只建议使用正确的指针,而不是其他类型。做出这样事情的代码具有极其糟糕的代码气味 - Rudy Velthuis
显示剩余8条评论
1个回答

6
如果被指向的类型不是托管类型,则这是安全的。在您的例子中,既Int64也Double都不是托管类型,因此这是安全的。
托管类型的一个例子是String、interface、Variant、匿名过程/方法、包含托管类型的记录等。
当您对托管类型使用New和Dispose时,对象必须被初始化和完成。当您对非托管类型使用New和Dispose时,它相当于调用GetMem和FreeMem。
实际上,您不需要被指向的类型具有相同的大小。调用FreeMem时未传递类型的大小。被指向的内存具有每个块的元数据,允许它释放整个块。

是的,我指的是未托管类型。我不知道它们被称为这样。AnsiChar和WideChar是托管的吗? - Marus Gradinaru
“你最后的一句话” - 如果我设置ReportMemoryLeaksOnShutdown:= True并分配一个PDouble,然后将其释放为PByte,可能这就是我没有收到内存泄漏报告的原因... - Marus Gradinaru
3
整个问题有一种类似跳楼运动的感觉...尽管发现自己确实可以穿着松鼠服从悬崖上跳下并安全着陆在目的地是一种启示性的刺激,但亲眼目睹这样做的惊人鲁莽会迫使深刻反思选择这种特定完成任务方式的智慧。 - J...
1
虽然它可能会工作,但我肯定永远不会建议将PInt64作为PDouble进行Dispose。我通常会说,应该只在正确的类型上进行Dispose。在错误的类型上进行Dispose是一种可怕的代码味道,在我看来。 - Rudy Velthuis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接