当你使用Ruby或者python时,你仅仅需要定义对象或者变量,而不用去关心它们在哪里.你不用去关心它是在堆(stack)还是在栈(heap)中.也许你选择的语言根本就不把变量放在栈中.
C是不同的,因为它使用真正的CPU时钟完成工作,它涉及到一块叫做堆的内存以及一块叫做栈的内存.它们之间有什么不同?这取决于你从哪里获得存储空间.
堆很容易解释,它就是电脑的剩余内存,你可以通过malloc
函数得到更多的空间.每次调用malloc
函数,OS利用内部函数为你注册一小块内存,同时返回指向这块内存的指针.当你使用完毕后,使用free
函数将它返还给OS,以便它可以被其它的程序使用.如果不这样做(执行free
释放空间)的话,就会造成内存泄漏.
栈是一块特殊的内存,它用来存储作为每个函数定义的局部变量的临时变量.函数的每个参数都会被入栈,然后在函数内部使用.它是一个真正的栈数据结构,所以,最后入栈的最先出栈.这通常发生在类似main
函数中像char action
和int id
这样的局部变量上.使用栈的好处是很简单,当函数退出时,C编译器将这些变量出栈.这样既方便,当变量在栈中又可以防止内存泄漏.
简单总结来说就是,如果一块内存,你不是用malloc
或者在一个函数中用malloc
得到的,那么它就是在栈中.
使用堆栈主要遇到的主要有下面三个问题:
- 如果你通过
malloc
得到一块内存,然后在栈中有一个指针指向这块内存,当函数退出时,这个指针就会被出栈,然后消失. - 如果你在栈中放了太多的数据(例如大的结构体或者数组),可能会引起’栈溢出’问题,导致程序退出.如果遇到这种情况,就使用堆.
- 如果你使用指针指向一些栈中的东西,然后将此指针当做参数传递或者返回值返回,接收这个指针的函数就会遇到”segmentation fault” (segfault)错误,因为真正的数据已经被出栈并且消失.指针现在指向的是一个不存在的空间.
Note: 本文节选自 《Learn C The Hard Way》Exercise 17: Heap And Stack Memory Allocation