Delphi:使用System.New()而不是局部变量有什么好处,除了节省少量内存?

Ast*_*oth 9 delphi pascal fpc

让我们回到基础.坦率地说,我之前从未使用NewDispose运作过.但是,在我阅读Embarcadero技术网站上的New()文档和包含的示例以及New()Delphi Basics解释之后,它在我脑海中留下了一些问题:

System.New()除了节省少量内存之外,使用而不是局部变量有什么好处?

常用代码示例New()或多或少如下:

  var
      pCustRec : ^TCustomer;
  begin
      New(pCustRec);
      pCustRec^.Name := 'Her indoors';
      pCustRec^.Age  := 55;
      Dispose(pCustRec);
  end;
Run Code Online (Sandbox Code Playgroud)

在什么情况下上面的代码比下面的代码更合适?

  var
      CustRec : TCustomer;
  begin
      CustRec.Name := 'Her indoors';
      CustRec.Age  := 55;
  end;
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 12

如果可以使用局部变量,请执行此操作.这是一条规则,几乎没有例外.这导致了最干净,最有效的代码.

如果需要在堆上进行分配,请使用动态数组,GetMem或New.分配记录时使用新建.

无法使用堆栈的示例包括在编译时未知大小的结构,或非常大的结构.但对于作为New的主要用例的记录,这些问题很少适用.

因此,如果您面对记录的堆栈与堆的选择,则堆栈始终是正确的选择.

  • 使用指针(即使用New)的另一个例子是增加链接列表,树等结构.每个元素都使用New()进行分配.FWIW,具有正确类型指针的New更适合GetMem,因为New将正确初始化内存,Dispose将正确地完成它. (4认同)

alz*_*mar 7

本地静态变量在有限堆栈上保留空间.分配的内存位于堆上,基本上所有内存都可用.

如上所述,堆栈空间是有限的,因此您应该避免使用大的局部变量以及通过值传递的大型参数(缺少var/ const在参数声明中).

上的内存使用情况的词:
1.简单类型(integer,char,string,double等等)直接位于在堆栈中.使用的字节数可以由sizeof(variable)函数确定.
2.这同样适用于记录变量和数组.3.指针和对象需要4/8字节.

  • 不.使用指针,它更容易实现;-)我不会创建一个复杂的迭代解决方案只是为了能够使用大型局部变量.我宁愿使用动态局部变量(或简单的对象).我可以从现实生活(商业)应用程序中给出足够的示例,其中使用大型(!)局部变量会炸毁堆栈. (2认同)

Jer*_*ers 7

从不同的角度来看:

两者都可能遭受缓冲区溢出并且可以被利用.

如果局部变量溢出,则会导致堆栈损坏.

如果堆变量溢出,则会导致堆损坏.

有人说堆栈损坏比堆损坏更容易被利用,但总的来说并非如此.

请注意,操作系统,处理器体系结构,库和语言中有各种机制可以帮助防止这些类型的攻击.

例如,在维基百科上提到了 DEP(数据执行保护),ASLR(地址空间布局随机化)等.

  • 您可以在完全调试模式下运行FastMM4来跟踪此类溢出.但是,如果OP问的话,你怎么能用固定大小的记录触发缓冲区溢出,没有指针算法和索引访问?使用堆栈分配的静态变量或New/Dispose,您就不能拥有这样的漏洞.恕我直言,你的回答超出范围,这里. (2认同)