• 什么是堆叠和堆叠?
  • 他们在电脑记忆中身处何方?
  • 它们在多大程度上受到操作系统或语言运行时间的控制?
  • 其范围是什么?
  • 是什么决定了它们的大小?
  • 是什么让一个更快?

当前回答

什么是堆叠?

堆叠是一堆物体, 通常是排列整齐的物体。

Enter image description here

计算机结构中的堆叠是数据以 " 最先进 " 方式添加或删除的内存区域。
在多行应用程序中,每串线索都有自己的堆叠。

什么是堆积物?

堆积成堆的杂乱无章的堆积物,

Enter image description here

在计算结构中,堆积是一个动态分配的内存领域,由操作系统或内存管理库自动管理。
在方案执行期间,堆积物上的内存被分配、分配和调整,并定期调整大小,这可能导致一个称为碎裂的问题。
当内存物体在小空格内分配时,就会发生碎片,而内存物体之间的空格太小,无法再持有更多的内存物体。
净结果为无法用于进一步分配内存的堆积空间的百分比。

两者加在一起

在一个多行应用程序中, 每串线索都有自己的堆叠。 但是, 所有不同的线条都会共享堆叠 。
因为不同的线条在一个多行应用程序中共享堆积, 这还意味着线条之间必须有一些协调, 以免它们试图同时访问和操作堆积中的同一块内存 。

哪个速度更快 堆叠还是堆叠 为什么?

堆叠比堆积要快得多
这是因为记忆在堆叠上分配的方式。
堆疊上的内存分配和移动堆叠指针一样简单。

对于新编程的人来说,
因为堆栈很小, 当您知道数据需要多少内存时, 或者如果您知道数据大小非常小时, 您会想要使用它 。
最好在知道数据需要大量内存时使用堆积, 或者你只是不确定你需要多少内存(如动态数组)。

Java 内存模型

Enter image description here

堆栈是存储本地变量(包括方法参数)的内存区域。当涉及到对象变量时,这些只是堆积中实际对象的引用(指针)。
每次一个对象被即时化时,都会留出一块堆积内存以保持该对象的数据(状态)。由于对象可以包含其他对象,有些数据实际上可以保留这些嵌套对象的引用。

其他回答

它们在哪里? 它们在哪里? (在真实的电脑记忆中)

回答: 两者都在记录和档案调控系统。

分会 :

内存就像一个书桌, HDDs/ SSDs( 永久存储) 像书架一样。 要阅读任何东西, 您必须在桌上打开一本书, 您只能在桌子上打开尽可能多的书。 要拿到一本书, 您必须把它从书架上拉出来, 然后在桌子上打开。 要退回一本书, 您必须关闭桌上的书架, 然后把它归还到书架上 。

堆积和堆积是我们给两种方式的汇编者提供的名称,它们将不同种类的数据储存在同一地点(即记录和档案管理)。

其范围是什么?
是什么决定了每个孩子的大小?
是什么让一个更快?

回答:

  1. 堆叠为静态(固定大小)数据

    a 。编译者在编译时读取代码中使用的变量类型。

    (一) 为这些变量分配固定数量的内存。
    二. 此记忆的大小无法增长 。

    b. b. 数据内存是毗连的( 单个区块) , 所以访问是 有时有时 比堆积速度快

    c. 用于以下目的:放置在堆叠堆叠上的一个物体,该物体在超过堆叠大小的运行时会生成内存,导致 堆堆堆堆堆溢溢溢出错误

  2. 堆肥用于动态(变化大小)数据

    a 。内存量仅受内存存储器可用空空空间数量的限制
    (一) 使用的数量在运行时可按需要增长或缩减。

    b. b. 数据由于项目在堆积上分配,只要在内存记录和档案记录室中存在空空空间,数据并不总是在毗连部分中,而 有时有时 访问比堆叠慢

    c. 用于以下目的:程序手动将项目与newkeyword 和 Must 手动移动此内存, 当它们使用它完成后 。
    一. 重复分配新内存的代码,在不再需要新内存时,不将新内存分配到内存泄漏。

分会 :

堆叠和堆积堆肥主要不是为了提高速度而引入;它们被引入是为了处理内存溢出。关于堆叠与堆积之间的第一个关注点应该是是否会出现内存溢出。如果一个对象打算将大小扩大为未知数量(如链接列表或其成员可以持有任意数量数据的对象),则将其放置在堆积上。尽可能使用 C++ 标准库(STL) 容器。矢量, 地图图图图地图, 和列表列表因为它们是记忆和速度效率高的,并增加使你的生活更加轻松(你不必担心记忆分配/迁移)。

在运行您的代码后, 如果您发现代码运行速度慢得令人无法接受, 然后返回并重新构思您的代码, 并查看它是否能够更有效地编程。 它可能会发现问题与堆叠或堆积完全无关( 比如使用迭代算法而不是循环算法, 看看 I/ O 对 CPU 的任务, 也许添加多读或多处理 ) 。

我说有时有时速度较慢/ 较快, 因为程序的速度可能与堆叠或堆叠上分配的项目无关 。

它们在多大程度上受到操作系统或语言运行时间的控制?

回答:

  • 堆叠大小由汇编者在汇编时确定。

  • 在运行期间,堆积大小各有不同。 (堆积在运行时与操作系统一起工作,以分配内存。)

分会 :

以下是更多关于控制和编译时间与运行时间操作的更多信息。

每台电脑都有独特的指令设置结构(ISA),即其硬件指令(例如“MOVE”、“JUMP”、“ADD”等)。

  • 操作系统只不过是一个资源管理者(控制如何/何时/和何处使用内存、处理器、装置和信息)。

  • 安全操作系统的ISA被称为光机其余命令被命名为扩展机内核是扩展机器的第一层。 它控制着类似

    • 确定要使用处理器(调度器)的任务,
    • 分配给任务(调度员)的内存多少或硬件登记册多少,以及
    • 执行任务的顺序(交通控制器)。
  • 当我们说“编译者”时,我们通常是指编译者、组装者和链接者在一起

    • 编译者将源代码转换为组装语言,并将其传给装配者,
    • 装配器将装配语言转换成机码(ISA命令),并传给链接器
    • 链接器将所有机器代码( 可能来自多个源文件) 合并成一个程序 。
  • 机器代码在被执行时传递到内核, 由内核决定它何时应该运行并控制, 但机器代码本身包含ISA命令, 用于请求文件, 请求内存等。 所以代码发布 ISA 命令, 但一切都要通过内核 。

其他人直接回答了你的问题,但是,在试图理解堆叠和堆叠时,我认为,考虑传统的UNIX进程的记忆布局(没有线条和线条)是有益的。mmap()- 以基于分配器为基础。记忆管理词汇表网页上有一个内存布局图。

堆堆和堆堆堆传统上位于进程的虚拟地址空间的对面。当访问时,堆堆会自动增长,最多以内核设定的大小(可以与setrlimit(RLIMIT_STACK, ...)))当内存分配器援引brk()sbrk()系统呼叫,绘制更多页的物理内存 进入该过程的虚拟地址空间。

在没有虚拟内存的系统中,例如一些嵌入系统,通常适用同样的基本布局,但堆叠和堆积大小固定。然而,在其他嵌入系统(例如基于微芯片的微控制器)中,程序堆叠是一个单独的内存块,无法通过数据移动指示处理,只能通过程序流指示(调用、返回等)进行间接修改或阅读。多个堆叠。从这个意义上说,堆叠是CPU结构的一个元素。

堆叠是记忆的一部分, 可以通过若干关键组装语言指令来操作, 如“ pop”( 移动并返回堆放中的值) 和“ push” (将值推到堆放中) , 但也可以调用( 调用子例程 - 将地址推回堆放中) 和调用( 从子例程返回 - 将堆放中的地址从堆放中跳出, 跳到堆放中) 。 这是堆叠指针登记册下的内存区域, 可根据需要设置 。 堆叠还用于将参数通过子例程, 并在调用子例程前保存登记册中的值 。

堆积是操作系统向一个应用程序提供的内存的一部分,通常通过像麦洛克这样的轮号。 在现代操作系统上,这个内存是一组只有呼叫程序才能进入的页面。

堆叠的大小在运行时确定, 通常在程序启动后不会增长。 在 C 程序中, 堆叠需要足够大, 以保持每个函数中所有声明的变量。 堆叠会根据需要动态增长, 但操作系统最终会发出呼唤( 它会增加的堆积量往往超过 merloc 所要求的值, 这样至少有些未来的中枢不需要返回内核以获取更多的内核内存。 这种行为通常可以自定义 )

因为您在启动程序前已经分配了堆叠, 所以在您使用堆叠之前, 您从不需要使用堆叠, 所以这有点优势。 实际上, 很难预测什么是快速的, 在拥有虚拟内存子系统的现代操作系统中什么是缓慢的, 因为这些页面是如何执行的, 在哪里存储的, 是一个执行细节 。

其他答案只是避免解释静态分配意味着什么。 因此,我将解释三种主要分配形式,以及它们通常与下面的堆积、堆叠和数据段的关系。 我还将在C/C++和Python中展示一些例子,以帮助人们理解。

“ 静态” (AKA静态分配) 变量没有在堆叠上分配 。 不要假设- 许多人这样做, 只是因为“ 静态” 听起来像“ 堆叠 ” 。 它们实际上既不存在于堆叠中,也不存在于堆叠中。 它们属于所谓的“ 堆叠” 的一部分 。数据元数据段.

然而,一般而言最好考虑 " 。范围范围" 和 "寿命寿命而不是"堆"和"堆"

范围指代码中哪些部分可以访问变量。本地范围(只能由当前函数访问)和全球范围尽管范围可能变得更加复杂,但范围(无论何处都可以进入)仍会变得更加复杂。

寿命指变量在程序执行期间分配和交易的时间。通常我们想到的是静静分配(在程序的整个整个期间,将始终可变,因此有助于在多个函数调用中储存相同信息)相对于自动分配(只有在对函数的单一次呼叫中,可变性才能持续,使该函数可用于存储仅在您函数期间使用、一旦完成即可丢弃的信息)和动态分配(期限在运行时界定的可变数据,而不是静态或自动的时间。)

尽管大多数编译者和口译员在使用堆叠、堆肥等方面也采取了类似的做法,但只要行为正确,编译者有时会打破这些公约。例如,由于优化,本地变量可能只存在于一个登记册中,或者完全删除,即使大多数本地变量存在于堆叠中。正如在几个评论中指出的,您可以自由使用一个甚至不使用堆叠或堆积的编译者,而是使用其他一些存储机制(因为堆叠和堆积对这很重要,因为堆叠和堆积对这很重要 ) 。

我将提供一个简单的附加注释的 C 代码来说明所有这一切。 最好的学习方法是在调试器下运行一个程序并观看行为。 如果您喜欢阅读 Python, 请跳到答案的结尾 :

// Statically allocated in the data segment when the program/DLL is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed from anywhere in the code
int someGlobalVariable;

// Statically allocated in the data segment when the program is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed from anywhere in this particular code file
static int someStaticVariable;

// "someArgument" is allocated on the stack each time MyFunction is called
// "someArgument" is deallocated when MyFunction returns
// scope - can be accessed only within MyFunction()
void MyFunction(int someArgument) {

    // Statically allocated in the data segment when the program is first loaded
    // Deallocated when the program/DLL exits
    // scope - can be accessed only within MyFunction()
    static int someLocalStaticVariable;

    // Allocated on the stack each time MyFunction is called
    // Deallocated when MyFunction returns
    // scope - can be accessed only within MyFunction()
    int someLocalVariable;

    // A *pointer* is allocated on the stack each time MyFunction is called
    // This pointer is deallocated when MyFunction returns
    // scope - the pointer can be accessed only within MyFunction()
    int* someDynamicVariable;

    // This line causes space for an integer to be allocated in the heap
    // when this line is executed. Note this is not at the beginning of
    // the call to MyFunction(), like the automatic variables
    // scope - only code within MyFunction() can access this space
    // *through this particular variable*.
    // However, if you pass the address somewhere else, that code
    // can access it too
    someDynamicVariable = new int;


    // This line deallocates the space for the integer in the heap.
    // If we did not write it, the memory would be "leaked".
    // Note a fundamental difference between the stack and heap
    // the heap must be managed. The stack is managed for us.
    delete someDynamicVariable;

    // In other cases, instead of deallocating this heap space you
    // might store the address somewhere more permanent to use later.
    // Some languages even take care of deallocation for you... but
    // always it needs to be taken care of at runtime by some mechanism.

    // When the function returns, someArgument, someLocalVariable
    // and the pointer someDynamicVariable are deallocated.
    // The space pointed to by someDynamicVariable was already
    // deallocated prior to returning.
    return;
}

// Note that someGlobalVariable, someStaticVariable and
// someLocalStaticVariable continue to exist, and are not
// deallocated until the program exits.

区分寿命和范围之所以重要,一个特别令人印象深刻的例子说明为什么区分寿命和范围很重要,那就是变量可以具有本地范围,但有静态的寿命,例如,在上文的代码样本中“某些本地静态可变性 ” 。这些变量可以使我们共同但非正式的命名习惯非常混乱。例如,当我们说“某些本地可变性 ” 。当地当地" 我们通常是指 "本地覆盖范围自动分配变量" 当我们说全球时,我们通常指 "全球范围静态分配可变数" 不幸的是,当它谈到类似的事情"缩放的静态分配变量"很多人只是说..."对不对?".

C/C++中的一些语法选择加剧了这一问题,例如许多人认为全球变量并非“静态”,

int var1; // Has global scope and static allocation
static int var2; // Has file scope and static allocation

int main() {return 0;}

请注意, 将关键字“ 静态” 放在上面的声明中会防止 var2 具有全球范围。 然而, 全球 val1 具有静态分布。 这不是直观的。 因此, 我试图在描述范围时从不使用“ 静态” 一词, 而是说“ 文件” 或“ 文件有限” 的范围。 但是许多人使用“ 静态” 或“ 静态范围” 来描述一个只能从一个代码文件中访问的变量。 在生命周期中, “ 静态” 是指“ 静态” 或“ 文件有限” 的范围。 但是许多人使用“ 静态” 或“ 静态范围” 来描述一个只能从一个代码文件中访问的变量。始终始终表示变量在程序启动时分配,在程序退出时进行交易。

有些人认为这些概念是特定C/C++/C++。它们不是。例如,下面的Python样本说明了所有三种分配类型(在翻译语言方面可能存在一些我无法进入这里的微妙差异)。

from datetime import datetime

class Animal:
    _FavoriteFood = 'Undefined' # _FavoriteFood is statically allocated

    def PetAnimal(self):
        curTime = datetime.time(datetime.now()) # curTime is automatically allocatedion
        print("Thank you for petting me. But it's " + str(curTime) + ", you should feed me. My favorite food is " + self._FavoriteFood)

class Cat(Animal):
    _FavoriteFood = 'tuna' # Note since we override, Cat class has its own statically allocated _FavoriteFood variable, different from Animal's

class Dog(Animal):
    _FavoriteFood = 'steak' # Likewise, the Dog class gets its own static variable. Important to note - this one static variable is shared among all instances of Dog, hence it is not dynamic!


if __name__ == "__main__":
    whiskers = Cat() # Dynamically allocated
    fido = Dog() # Dynamically allocated
    rinTinTin = Dog() # Dynamically allocated

    whiskers.PetAnimal()
    fido.PetAnimal()
    rinTinTin.PetAnimal()

    Dog._FavoriteFood = 'milkbones'
    whiskers.PetAnimal()
    fido.PetAnimal()
    rinTinTin.PetAnimal()

# Output is:
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is tuna
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is steak
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is steak
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is tuna
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is milkbones
# Thank you for petting me. But it's 13:05:02.256000, you should feed me. My favorite food is milkbones

堆堆叠

  • 非常快速接入
  • 不必明确排除可变变量
  • 由CPU有效管理空间,内存不会分散
  • 仅本地变量
  • 对堆叠大小的限制(取决于OS)
  • 变量无法调整大小

堆肥

  • 可在全球范围内访问变量
  • 内存大小无限制
  • (相对)获取较慢
  • 没有保证有效使用空间的保证,随着时间推移,记忆可能会变得支离破碎,因为分配了记忆区块,然后释放了
  • 您必须管理内存( 您负责分配和释放变量) 。
  • 可使用 elloc () 调整变量大小