您的位置:首页 > 其它

.net 垃圾回收学习[Stack 和 Heap的理解][续2]

2011-08-20 16:44 489 查看
from: http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap

这里继续看其他人答案和补充,深入理解。

答案四。
关于Stack和Heap的实现在不同的编译器和处理器架构之间差异很大,但是,这里有个简化的解释。

stack和heap都是由操作系统分配的内存区域。(通常是映射到物理内存的虚拟内存)

在一个多线程的环境中,每一个线程都会有自己独立的stack,但是会共享一个heap.对于heap的并发访问是需要被控制的,但是栈上则没有此要求。

The heap:

heap通常包含一个记录使用的和空闲的内存块的List。在heap上分配新的空间通常通过在空闲的块上创建合适的内存块而来,这需要更新heap维护的使用情况list. 关于heap上的内存块的使用情况信息也被存储在heap上,通常在每一个内存块的前面的一块区域。、

新的内存块通常从低地址到高地址被分配,heap也随之增大。当heap太小以至于不能分配足够多的空间的时候,heap通常可以向os申请更多的空间。

The Stack:

Stack和CPU上一个名为stack pointer的特殊寄存器紧密关联。Stack pointer通常指向栈的顶部。

CPU通常有特殊的将值压入Stack和将值从Stack弹出的指令。弹出执行(pop)将会增加stack pointer并且取出来stack pointer指向的Value。存储和检索的值是CPU寄存器的值。

当一个函数被调用的时候,CPU采用特殊指令push当前的指令指针(instruction pinter), 比如说: 在stack执行的代码的地址。 然后CPU设置instruction pointer 为当前被调用的函数地址,这样CPU就跳转到了当前的函数上。然后,当函数返回的时候,上次压入Stack的intruction pointer被从stack中弹出,然后在调用函数的地方继续执行。

当函数开始执行的时候,Stack pointer 被减少以便在Stack为局部变量分配更多的空间。假如函数有一个32位的变量,那么四个字节将会在stack上被设置。当函数返回的时候,Stack pointer也返回,以便释放已经分配的空间。

假如a function has parameters these are pushed onto the stack before the call to the function. The code in the function is then able to navigate up the stack from the current stack pointer to locate these values。

Nesting function calls works like a charm. Each new call will allocate function parameters, the return address and space for local variables and these activation records can be stacked for nested calls and will unwind in the correct way when the functions return.

As the stack is a limited block of memory you can cause a stack overflow by calling too many nested functions and/or allocating too much space for local variables. Often the memory area used for the stack is set up in such a way that writing below the bottom (the lowest address) of the stack will trigger a trap or exception in the CPU. This exceptional condition can then be caught by the runtime and converted into some kind of stack overflow exception.

Can a function be allocated on the heap instead of a stack?
No, activation records for functions (i.e. local or automatic variables) are allocated on the stack that is used not only to store these variables, but also keep track of nested function calls.
How the heap is managed is really up to the run-time environment. C uses malloc and C++ uses new, but many other languages have garbage collection.
However, the stack is more low level feature closely tied to the processor architecture. Growing the heap when there is not enough space isn't too hard since it can be implemented in the library call that handles the heap. However, growing the stack is often impossible as the stack overflow only is discovered when it is too late and shutting down the thread of execution is the only viable option.

答案五

这是一个补充答案,但是比较深入一些。


up vote 10 down vote

Others have answered the broad strokes pretty well, so I'll throw in a few details.

Stack and heap need not be singular. A common situation in which you have more than one stack is if you have more than one thread in a process. In this case each thread has its own stack. You can also have more than one heap, for example some DLL configurations can result in different DLLs allocating from different heaps, which is why it's generally a bad idea to release memory allocated by a different library.

In C you can get the benefit of variable length allocation through the use of alloca, which allocates on the stack, as opposed to alloc, which allocates on the heap. This memory won't survive your return statement, but it's useful for a scratch buffer.

On windows making a huge temporary buffer that you don't use much of is not free. This is because the compiler will generate a stack probe loop that is called every time your function is entered to make sure the stack exists (because windows uses a single guard page at the end of your stack to detect when it needs to grow the stack, if you access memory more than one page off the end of the stack you will crash). Example:

void myfunction()
{
char big[10000000];
// do something that only uses for first 1K of big 99% of the time.
}

link|improve this answer

answered Sep 17 '08 at 4



翻译:


补充几个细节:

1. stack和heap不需要一对一。 一个常见的情况是假如你在一个进程中有多个线程的话,你会拥有不止一个Stack,每个线程都有自己的Stack。你也可以拥有多个Heap,比如说有些DLL的配置会导致DLL从不同的heap上分配空间,这也是为什么释放一个不同的Library的memory是糟糕的主意。

2. 在C语言中,使用alloca可以在stack上分配空间,使用alloc,则是在heap上分配空间。使用alloca分配的内存在函数返回后会被回收,但是可以作为一个临时的缓冲。

3. 在windows上,申请一个巨大的而不用的临时缓存区域是十分昂贵的。因为当你的程序每次被调用的时候,编译器会生成一个探测循环以确保Stack存在。(因为windows使用一个单一的的保护页来监测是否需要增大Stack,当你在Stack的尾部获取比One Page大的内存的时候你会失败)比如:

void myfunction()
{
char big[10000000];
// do something that only uses for first 1K of big 99% of the time.
}



附:SCratch:

形容词 1. (俚语)东拼西凑的;(船员、球队等)临时凑成的;凑合的;庞杂的,各种各样的。 2. 碰巧的;偶然的。 3. 平等比赛的;(赛跑等)无让步的。 4. 随便写的;打草稿用的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐