堆叠和堆肥是什么?它们实际上位于计算机的内存中在哪里?它们在多大程度上被操作时间或语言控制?它们的范围是什么?它们的大小是什么?它们大小是什么?一个的大小是什么使一个更快?
当前回答
简单的说, 堆栈是创建本地变量的地方。 另外, 每次您调用一个子例程, 程序计数器( 下个机器指令的指针) 和任何重要的注册器, 有时参数会被推到堆栈上。 然后子例程内的任何本地变量都会被推到堆叠上( 并在那里使用 ) 。 当子例程完成时, 所有的事物都会从堆栈中跳出来。 pc 和 注册数据会得到并放回原位, 所以您的 progra 就会被推到堆叠上( 并在那里使用 ) 。
它是一个特殊的数据结构,可以跟踪不同大小的记忆区块及其分布状况。
在“古典”系统上, 堆叠指针是放在记忆底部开始的, 堆积指针是从顶部开始的, 并且它们相互向上发展。 如果它们重叠, 你就会脱离公羊。 但是, 与现代多孔的套索不起作用。 每条线必须有自己的堆叠, 并且它们可以动态地生成 。
其他回答
简单的说, 堆栈是创建本地变量的地方。 另外, 每次您调用一个子例程, 程序计数器( 下个机器指令的指针) 和任何重要的注册器, 有时参数会被推到堆栈上。 然后子例程内的任何本地变量都会被推到堆叠上( 并在那里使用 ) 。 当子例程完成时, 所有的事物都会从堆栈中跳出来。 pc 和 注册数据会得到并放回原位, 所以您的 progra 就会被推到堆叠上( 并在那里使用 ) 。
它是一个特殊的数据结构,可以跟踪不同大小的记忆区块及其分布状况。
在“古典”系统上, 堆叠指针是放在记忆底部开始的, 堆积指针是从顶部开始的, 并且它们相互向上发展。 如果它们重叠, 你就会脱离公羊。 但是, 与现代多孔的套索不起作用。 每条线必须有自己的堆叠, 并且它们可以动态地生成 。
cpu 堆和堆积与堆积与堆积与堆积与堆积与堆积之间,
所有现代的 cpus 都与“ 相同” 微处理理论合作: 它们都基于所谓的“ 注册者” 和一些“ 堆叠” 来取得性能。 所有 cpus 从一开始就有堆叠登记簿, 他们总是在这里, 说话的方式,如我所知。 组装语言从一开始就是相同的, 尽管从一开始, 直到... 微软和中间语言( i) 都改变了范式, 有了一种 oo 虚拟机组装语言。 这样我们就可以有一些 cli/ cil 。
cpus有堆叠登记册来加快存取记忆的速度,但与其他登记册相比,这些登记册是有限的,以充分利用所有可用于处理过程的存储器。 这就是为什么我们谈论堆叠和堆积分配的原因。
简而言之,一般而言,堆积是慢慢的,用于“全球”实例和对象内容,因为堆叠小而快,用于“本地”变量和参考(隐藏的指针要忘记管理这些变量和参考)。
所以当我们在一个方法中使用新关键字时, 引用( int) 是在堆叠中创建的, 但是对象及其全部内容( 价值类型以及对象) 都在堆积中创建, 如果我记得的话。 但是本地基本值类型和阵列是在堆叠中创建的 。
内存存存取的差别在于单元格的参考级别:处理堆积,即整个过程的记忆,在处理 cpu 登记册方面要求比处理当地“更多” 的堆叠更为复杂,因为如果我记得, cpu 堆积登记册被用作基地址。
这就是为什么当我们有非常长或无限的循环电话或循环时, 我们很快地被堆积物溢出, 而不冻结现代电脑上的系统...
cheap(ing) 与. net 中的堆叠(ing) 。
堆堆堆和堆堆:知道差别
储存的静态类内存分配c
堆叠和堆放在哪里?
https://en.wikipedia.org/wiki/Memory_management
https://en.wikipedia.org/wiki/Stack_register
功率语言资源:
组组编程辅导
64和ia-32建筑软件开发手册
其他答案只是避免解释静态分配意味着什么。 所以我会解释三种主要分配形式,以及它们通常与下面的堆积、堆叠和数据段的关系。 我还会在 c/c++ 和 python 中展示一些例子,以帮助人们理解。
静态( 静态分配) 变量没有在堆叠上分配。 不要假设- 许多人只是因为“ 静态” 听起来像“ 堆叠 ” 。 它们实际上既不存在于堆叠中, 也不存在于堆叠中。 它们属于所谓的数据段 。
然而,一般而言,最好考虑“范围”和“终生”,而不是“堆积”和“堆积”。
范围指代码中哪些部分可以访问变量。 我们一般认为本地范围(只能通过当前函数访问)与全球范围(任何地方都可以访问)不同,尽管范围可能变得更加复杂。
当一个变量在程序执行期间被分配和交易时, 其使用寿命值是指变量在程序执行期间被分配和交易。 我们通常会想到静态分配( 在整个程序期间会持续不变, 使得它可用于在多个函数调用中存储相同的信息), 而会想到自动分配( 仅在对函数的单次调用中持续不变, 使得它可用于存储仅在您函数期间使用、 一旦完成即可丢弃的信息) 相对于动态
尽管大多数编译者和口译员在使用堆叠、堆堆堆等方面也采取了类似的做法,但只要行为正确,编译者有时会打破这些公约。例如,由于优化,本地变量可能只存在于登记册中,或者完全删除,即使大多数本地变量存在于堆叠中。正如在几个评论中所指出的,你可以自由实施一个甚至不使用堆叠或堆叠的编译者,但有些则可以使用
i 将提供一些简单的附加说明的 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++/ 具体化的。 它们不是。 例如,下面的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
其他人直接回答了您的问题, 但是当试图理解堆叠和堆积时, 我认为考虑传统的 unix 进程( 没有线条和基于 mmap () 的缩放符) 的内存布局( 没有线条和 mmap () 的缩放符 ) 。 内存管理词汇表网页有一张内存布局图 。
堆叠和堆肥传统上位于进程虚拟地址空间的对面。 堆叠在存取时自动增长, 以内核设定的大小( 内核可以使用设置限制( rlimit_ stack,...) 调整) 。 当内存分配器引用 brk () 或 sbrk () 系统调用时, 堆叠会增长, 将更多页的物理内存映入进程的虚拟地址空间 。
在没有虚拟内存的系统中,例如一些嵌入系统,通常适用同样的基本布局,但堆叠和堆积大小固定。然而,在其他嵌入系统中(例如基于微芯片的微控制器),程序堆叠是一个单独的内存块,无法通过数据移动指示处理,只能通过程序流指示(调用、返回等)进行间接修改或阅读。
(我将这一答案从另一个或多或少是本问题的代名词的问题移出。 )
您问题的答案是具体执行问题,可能因汇编者和处理结构而异。然而,这里是简单的解释。
堆叠和堆积都是从基本操作系统分配的内存区域(通常是虚拟内存,根据需要绘制成物理内存)。 在多轨环境中,每条线将有自己的完全独立的堆叠,但他们将共享堆叠。同时存取必须控制在堆积上,不可能在堆叠上。
堆积物,
堆积中含有一个用过的和自由的区块的链接列表。 堆积( 由新的或中转的) 上的新分配通过从一个自由区块中创建一个合适的区块来满足。 这需要更新堆积中的区块清单。 堆积中的区块的元信息也通常储存在堆积中, 保存在每个区块前面的小区域中。 当堆积中的新区块往往从下面的地址分配到更高的地址。 因此, 您可以将堆积视为一个堆积 o 。
调
堆叠堆叠
堆叠通常与名为堆叠指针的 cupu 上的特殊登记簿密切配合。 最初, 堆叠指针指向堆叠的顶部( 堆叠上的最高地址 ) 。 堆叠有将值推到堆叠上并将其从堆叠中弹出的特殊指令。 每一次推移都存储在堆叠指针当前位置的值, 并减少堆叠指针。 流行会检索堆叠指针指向的值, 然后增加堆叠指针( 不要) 。
调
能否在堆叠上而不是堆叠上分配函数 ?
否,函数(即本地变量或自动变量)的激活记录在堆栈上分配,不仅用于存储这些变量,还用于跟踪嵌套功能电话。
如何管理堆肥真的取决于运行时间环境。 c 使用中转器, c++ 使用新的, 但很多其他语言都有垃圾收集 。
然而,堆叠是一个更低层次的特征,它与处理器结构紧密相连。 当没有足够的空间时, 堆叠会生长成堆不会太难, 因为可以在处理堆叠的图书馆电话中执行。 然而, 堆叠的堆叠往往不可能增长, 因为堆叠溢出的时间太晚才被发现; 关闭行刑线是唯一可行的选择。