详解C/C++内存区域划分(简而易懂)
在C/C++程序运行期间,内存会被划分为不同的段,每个段有不同的使用方式和属性。
内存划分
栈(stack)
栈是一种在程序运行时内存自动分配和释放的区域,它存储程序执行过程中的各种变量。栈的特点是先进后出,后进先出,因此被称为“后进先出”(LIFO)。
栈的大小是有限的,一般来说,栈的大小在几兆到几十兆之间,超过这个范围就会引起“栈溢出”错误。
以下是一个使用栈进行递归运算的示例:
int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
int main() {
int n = 5;
int result = factorial(n);
printf("%d! = %d\n", n, result);
return 0;
}
在以上示例中,递归调用 factorial
函数时,每次调用会在栈上分配一块内存,用于存储参数和局部变量。当函数执行结束后,这段内存会被释放,供后续调用使用。
堆(heap)
堆是程序运行时动态分配内存的区域,也就是所有通过 malloc
、calloc
、realloc
、new
等操作申请的内存空间都在堆中。
堆的大小一般比较大,可以达到几百兆甚至几个GB,因此内存泄露(没有及时释放堆内存)会导致严重的系统性能问题。
以下是一个使用 malloc
动态分配内存的示例:
int main() {
int* p1 = (int*) malloc(sizeof(int));
*p1 = 123;
printf("*p1 = %d\n", *p1);
int* p2 = (int*) malloc(sizeof(int) * 3);
p2[0] = 1;
p2[1] = 2;
p2[2] = 3;
printf("p2[0] = %d, p2[1] = %d, p2[2] = %d\n", p2[0], p2[1], p2[2]);
free(p1);
free(p2);
return 0;
}
在以上示例中,通过 malloc
分配了两次内存空间,其中 p1
的大小为 sizeof(int)
,而 p2
的大小为 sizeof(int) * 3
,即三个整数的大小。最后通过 free
函数释放了分配的内存空间。
数据段(data segment)
数据段是程序运行时存储全局变量和静态变量的区域,它在程序加载时分配并初始化。
对于全局变量和静态变量,它们都有默认的初始值,如果没有显式初始化,则会默认为0。
以下是一个在数据段中存储全局变量和静态变量的示例:
#include <stdio.h>
int global_var;
int main() {
static int static_var;
printf("global_var = %d\n", global_var);
printf("static_var = %d\n", static_var);
global_var = 123;
static_var = 456;
printf("global_var = %d\n", global_var);
printf("static_var = %d\n", static_var);
return 0;
}
在以上示例中,global_var
是一个全局变量,在程序加载时会将其初始化为0,static_var
是一个静态变量,在程序运行时会将其初始化为0。最后通过赋值修改了它们的值。
代码段(code segment)
代码段是存储程序指令的区域,它在程序加载时被分配,并在程序执行过程中运行,同时会受到操作系统的保护。
以下是一个使用代码段存储指令的示例:
#include <stdio.h>
int main() {
printf("Hello, world!\n");
return 0;
}
在以上示例中,printf
函数的指令就存储在代码段中,程序运行时会从代码段中读取指令并执行。
总结
本文介绍了C/C++程序在运行时内存的划分方式,包括栈、堆、数据段和代码段四个部分。在实际编程中,了解这些内存区域的使用方式和限制,有助于更好地编写高效、可靠的程序,避免一些常见的内存问题。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解C/C++内存区域划分(简而易懂) - Python技术站