最近在看PHP源碼解析,涉及到堆棧存儲區的知識,而我對於這個卻不太清楚,因此,看了一下相關資料,總結一下。
棧
棧,存儲函數中的局部變量(臨時變量),存儲函數地址,棧是后進先出的結構,由CPU管理和優化。
使用棧存儲變量的優勢在於:你不用再管理內存了,不必手動分配內存或釋放它,此外,由於CPU相關的優化,讀取寫入的效率也很高。
關於棧需要注意的一點是:存儲在棧上的變量的大小是有限制的,而堆卻不是。
堆
堆是計算機內存的一塊區域,不會自動為你管理內存,也不是由CPU嚴格管理的。它是一個更自由的內存區域(並且更大)。要在堆上分配內存,必須使用 malloc
或 calloc
,它們是內置的C函數。一旦在堆上分配了內存,你就負責在不需要它時使用 free()
釋放內存。如果沒有做到這一點,程序將會出現所謂的 內存泄漏,也就是說,堆上的內存仍被保留,但其他進程無法使用。
示例
下面這個例子展示了在棧上創建變量的情況:
#include <stdio.h>
double multiplyByTwo (double input) {
double twice = input * 2.0;
return twice;
}
int main (int argc, char *argv[])
{
int age = 30;
double salary = 12345.67;
double myList[3] = {1.2, 2.3, 3.4};
printf("double your salary is %.3f\n", multiplyByTwo(salary));
return 0;
}
第10,11,12行創建了變量:int、double和double數組。這些變量被推入棧中,當main退出時,這些變量自動從棧中彈出。類似的,函數multiplyByTwo()中的twice變量被推入棧中(當multiplyByTwo()被調用時),當multiplyByTwo()退出時,twice被彈出並且消失不見。
下面是一個在堆上分配內存的例子:
#include <stdio.h>
#include <stdlib.h>
double *multiplyByTwo (double *input) {
double *twice = malloc(sizeof(double));
*twice = *input * 2.0;
return twice;
}
int main (int argc, char *argv[])
{
int *age = malloc(sizeof(int));
*age = 30;
double *salary = malloc(sizeof(double));
*salary = 12345.67;
double *myList = malloc(3 * sizeof(double));
myList[0] = 1.2;
myList[1] = 2.3;
myList[2] = 3.4;
double *twiceSalary = multiplyByTwo(salary);
printf("double your salary is %.3f\n", *twiceSalary);
free(age);
free(salary);
free(myList);
free(twiceSalary);
return 0;
}
何時使用堆?
什么時候應當使用堆,什么時候使用棧?如果你需要分配大塊內存(一個大數組,大的結構體),並且你想保持相當長的時間,此時應當使用堆。如果你只處理相對小的變量,只在函數的范圍內使用,那么使用棧,它更容易也更快。如果你需要變量類似動態大小的數組或結構體,那么應當使用堆。
參考來源
- https://www.gribblelab.org/CBootCamp/7_Memory_Stack_vs_Heap.html
- https://www.learncpp.com/cpp-tutorial/79-the-stack-and-the-heap/
PS - 個人博客鏈接:變量存儲區:堆和棧