理解delphi中的内存分配

从代码中调用函数“DoStackOverflow”一次,您将得到Delphi引发的EStackOverflow错误,并显示消息“stack overflow”。...

从代码中调用函数“DoStackOverflow”一次,您将得到Delphi引发的EStackOverflow错误,并显示消息“stack overflow”。

Hands holding computer hard drivefunction DoStackOverflow : integer; begin result := 1 + DoStackOverflow; end;

这个“堆栈”是什么?为什么使用上面的代码会出现溢出?

因此,DoStackOverflow函数递归地调用自己——没有“退出策略”——它只是继续旋转,从不退出。

您可以做的一个快速修复方法是清除明显的bug,并确保函数在某个点存在(这样您的代码就可以从调用函数的位置继续执行)。

你继续前进,你永远不会回头,不关心现在已经解决的bug/异常。

然而,问题仍然存在:这个堆栈是什么?为什么会出现溢出?

delphi应用程序中的内存

当您开始在Delphi中编程时,您可能会遇到类似上面的错误,您可以解决它并继续前进。这与内存分配有关。大多数情况下,只要释放所创建的内容,您就不会关心内存分配。

随着您在Delphi中获得更多的经验,您开始创建自己的类,实例化它们,关心内存管理等等。

您将在帮助中阅读类似“局部变量(在过程和函数中声明)驻留在应用程序堆栈中”的内容,并且类也是引用类型,因此它们不会在赋值时复制,而是通过引用传递,并在堆上分配。

那么,什么是“堆栈”,什么是“堆”?

堆栈与堆

在Windows上运行应用程序时,内存中有三个区域用于存储数据:全局内存、堆和堆栈。

全局变量(其值/数据)存储在全局内存中。全局变量的内存在程序启动时由应用程序保留,并在程序终止前保持分配状态。全局变量的内存称为“数据段”。

由于全局内存只在程序终止时分配和释放一次,因此本文不关心它。

堆栈和堆是进行动态内存分配的地方:为函数创建变量时,向函数发送参数并使用/传递其结果值时,创建类实例时。

什么是堆栈(stack)?

在函数中声明变量时,保存变量所需的内存将从堆栈中分配。您只需编写“var x:integer”,在函数中使用“x”,当函数退出时,您不关心内存分配或释放。当变量超出范围(代码退出函数)时,堆栈上占用的内存将被释放。

堆栈内存是使用后进先出方法动态分配的。

在Delphi程序中,堆栈内存由

  • 局部例程(方法、过程、函数)变量。
  • 例程参数和返回类型。
  • Windows API函数调用。
  • 记录(这就是为什么不必显式创建记录类型的实例)。

您不必显式释放堆栈上的内存,因为当您(例如)向函数声明局部变量时,内存会自动神奇地分配给您。当函数退出时(有时甚至由于Delphi编译器优化而提前退出),变量的内存将自动神奇地释放。

默认情况下,堆栈内存大小对于您的Delphi程序(尽管很复杂)来说是足够大的。项目链接器选项上的“最大堆栈大小”和“最小堆栈大小”值指定默认值——在99.99%范围内,您无需更改此值。

将堆栈视为一堆内存块。当您声明/使用局部变量时,Delphi内存管理器将从顶部拾取块并使用它,当不再需要时,它将返回堆栈。

使用堆栈中的局部变量内存时,局部变量在声明时不会初始化。在某个函数中声明一个变量“var x:integer”,并在输入该函数时尝试读取该值——x将有一些“奇怪的”非零值。所以,在读取局部变量的值之前,请始终初始化(或设置值)。

由于后进先出(LIFO),堆栈(内存分配)操作速度很快,因为管理堆栈只需要几个操作(推送、弹出)。

什么是堆(heap)?

堆是存储动态分配内存的内存区域。创建类的实例时,将从堆中分配内存。

在Delphi程序中,堆内存由/when使用

  • 创建类的实例。
  • 创建动态数组并调整其大小。
  • 使用GetMem、FreeMem、New和Dispose()显式分配内存。
  • 使用ANSI/wide/Unicode字符串、变量和接口(由Delphi自动管理)。

堆内存没有很好的布局,分配内存块是有一定顺序的。堆看起来像一罐弹珠。堆中的内存分配是随机的,这里的一个块比那里的一个块大。因此,堆操作比堆栈上的操作慢一点。

当您请求一个新的内存块(即创建一个类的实例)时,Delphi内存管理器将为您处理这个问题:您将得到一个新的内存块或一个已使用并丢弃的内存块。

堆由所有虚拟内存(RAM和磁盘空间)组成。

手动分配内存

现在,关于内存的所有内容都已清楚,您可以安全地(在大多数情况下)忽略上述内容,继续编写Delphi程序,就像昨天一样。

当然,您应该知道何时以及如何手动分配/释放内存。

之所以提出“EStackOverflow”(从本文开始),是因为每次调用DoStackOverflow时,都会从堆栈中使用一段新的内存,并且堆栈具有限制。就这么简单。

  • 发表于 2021-09-15 03:47
  • 阅读 ( 190 )
  • 分类:编程

你可能感兴趣的文章

新的(new)和C++中删除运算符(delete operator in c++)的区别

C++中new和Delphi运算符的主要区别在于new被用来为对象或数组分配内存,而DELATE用于释放使用新运算符分配的内存。 有两种类型的记忆作为静态和动态记忆。假设一个语句,比如int a;int数组[10];程序员已经知道这些变量需要多...

  • 发布于 2021-07-01 04:35
  • 阅读 ( 179 )

如何将媒体文件嵌入delphi可执行文件(rc/.res)(embed media files into a delphi executable (rc/.res))

...止其他人操纵这些加载项文件。 本文将向您展示如何在Delphi可执行文件中嵌入(和使用)声音文件、视频剪辑、动画以及更一般的任何类型的二进制文件。对于最通用的用途,您将看到如何将MP3文件放入Delphi exe中。 资源文...

  • 发布于 2021-09-06 15:08
  • 阅读 ( 190 )

将项目添加到tpopup delphi菜单

在Delphi应用程序中使用菜单或弹出菜单时,在大多数情况下,都是在设计时创建菜单项的。每个菜单项都由一个TMenuItem Delphi类表示。当用户选择(单击)一个项目时,OnClick事件将被触发,以供您(作为开发人员)获取该事件并...

  • 发布于 2021-09-06 15:10
  • 阅读 ( 164 )

理解delphi项目和单元源文件

简而言之,Delphi项目只是组成由Delphi创建的应用程序的文件集合。DPR是用于Delphi项目文件格式的文件扩展名,用于存储与项目相关的所有文件。这包括其他Delphi文件类型,如表单文件(DFM)和单元源文件(.PASs)。 由于Delphi...

  • 发布于 2021-09-06 15:15
  • 阅读 ( 171 )

程序退出时delphi中的内存泄漏通知

自Delphi 2006以来的所有Delphi版本都有一个更新的内存管理器,该管理器速度更快,功能更丰富。 “新”内存管理器最出色的功能之一是允许应用程序注册(和注销)预期内存泄漏,并在程序关闭时报告意外内存泄漏。 使用De...

  • 发布于 2021-09-06 15:15
  • 阅读 ( 165 )

delphi中的sql

...形式,允许您选择、插入、更新、查找数据位置等。 delphi中的tquery 如果要在应用程序中使用SQL,您将非常熟悉TQuery组件。Delphi使您的应用程序能够通过TQuery组件直接使用SQL语法来访问Paradox和dBase表(使用本地SQL—ANSI标准SQL...

  • 发布于 2021-09-08 10:40
  • 阅读 ( 183 )

delphi的顺序和枚举数据类型

Delphi的编程语言是强类型语言的一个例子。这意味着所有变量必须是某种类型。类型本质上是一种数据的名称。当我们声明一个变量时,我们必须指定它的类型,它决定了变量可以保存的值集以及可以对其执行的操作。 Delphi...

  • 发布于 2021-09-10 23:38
  • 阅读 ( 195 )

在delphi应用程序中使用tclientdataset的指南

...的结构。还演示了创建虚拟和嵌套数据集字段的方法。 理解ClientDataSet索引ClientDataSet不会从加载的数据中获取其索引。如果需要,必须显式定义索引。本文将向您展示如何在设计时或运行时执行此操作。 导航和编辑ClientDataSet...

  • 发布于 2021-09-15 03:38
  • 阅读 ( 150 )

优化delphi程序的内存使用

...活动,最终降低计算机的速度。 02 2006年 何时在delphi应用程序中创建表单 假设您要设计一个包含主窗体和两个附加(模态)窗体的程序。通常,根据您的Delphi版本,Delphi将把表单插入到项目单元(DPR文件)中,并包...

  • 发布于 2021-09-15 03:43
  • 阅读 ( 198 )

delphi中的基本剪贴板操作(剪切/复制/粘贴)

...或图形的容器。本文将向您展示如何使用TClipboard对象在Delphi应用程序中实现剪切复制粘贴功能。 一般剪贴板 您可能知道,剪贴板一次只能保存一段相同类型的数据进行剪切、复制和粘贴。如果我们以相同的格式将新信息发...

  • 发布于 2021-09-15 03:52
  • 阅读 ( 273 )
seE5538
seE5538

0 篇文章

相关推荐