栈(Stack)和堆(Heap)
目前来说我们知道怎么去声明一个基础类型的变量,比如int,float,等等。以及复杂数据类型数组和结构,声明它们的时候C会把这些变量放在栈上。每个线程都有一个栈,而程序通常只有一个堆。
栈(Stack)
什么是栈?它是内存中一块特殊的区域,用于保存在函数中声明的零时变量(其中也包括main()
函数)。栈是LIFO(Last in First Out 后进先出)的数据结构,进出操作是由CPU来管理和优化的。每当函数声明了一个变量,该变量就会被推入(Pushed)栈中。每当函数退出时,所有的变量都会被函数推出栈,并被释放掉(Free)。一旦变量被释放,该内存区域就可以被其他栈变量使用。
使用栈的优势是它会为你管理内存,而不需要你手动去分配或者释放内存。更进一步说,由于CPU可以有效地管理栈内存,所以从栈中读写变量是很快的。
理解栈的关键是需要知道函数什么时候退出,此时栈中所有的变量被推出,因此栈变量是局部的(也就是局部变量)。C中经常出现的一个错误就是,在函数返回以后去访问函数内部中栈变量。
如果使用太多的栈空间会导致溢出,比如在使用递归的时候,该函数使用了太多的局部变量在递归过程中就有可能造成栈溢出。
总结
- 栈是LIFO数据结构;
- CPU管理内存,而不需要手动去管理。正是因为这个原因从栈中读写变量很快的;
- 栈变量是局部的(也就是局部变量);
- 栈的容量会随着函数的Push和Pop变化;
堆(Heap)
堆也是内存中一块特定区域,但是CPU并不会自动管理相关的操作,而且它的空间大小会有一定的浮动。在堆上分配内存的时候,在C中使用malloc()
和calloc()
函数。在不需要堆上这块内存之后,需要使用free()
函数释放掉它。如果不释放的话就会造成内存泄漏,这块内存就会被闲置。
和栈不同之处在于,堆内存数据的读写速度会比栈慢。
栈(Stack)和堆(Heap)的差异
配置堆栈大小
堆的大小在程序启动时分配,数值在不同操作系统中可能有所不同。
在Cocoa中想要修改线程的栈大小的话,可以使用NSThread
的实例方法setStackSize:
,如果使用POSIX线程技术创建的线程的话,想要设置栈大小的话使用pthread_attr_setstacksize
函数。
⚠️如果要设置栈大小就必须要在创建线程之前完成。
|
|
生命周期
栈是和线程相关联的,意思就是说当线程退出时,栈被回收。而堆通常是在启动程序时分配,当程序退出之后被回收。
什么时候使用栈什么时候使用堆
- 需要申请较大内存空间(比如struct,array之类的),而且需要该变量存在较长时间,就是将该变量放在堆中;
- 如果需要动态修改struct或者array的大小,将该变量放在堆上。使用
malloc(),calloc(),realloc()和free()
等函数来管理内存; - 如果使用相对较小的变量,并且只在函数中使用它们,此时该变量就存在于栈上。这样做会更快而且更简单;