C语言内存区域划分
在C语言中,内存区域主要分为:
栈区(Stack):
1.由编译器自动分配和释放
2.利用栈存储一些临时变量,包括函数形参、函数内部局部变量、返回值等
3.栈的操作遵循“后进先出”(LIFO)的原则
看下面的程序:
#include <stdio.h>
int add(int a, int b)
{
int result = a + b;
return result ;
}
int main(int argc, const char *argv[])
{
int x = 5;
int y = 3;
int sum = add(x,y);
printf("&x=%p\n&y=%p\n&sum=%p\n", &x, &y, &sum);
return 0;
}
main函数的x,y,sum都分配在栈上,add函数中,a,b,result也是分配在栈上,看一下运行结果:
sum的地址>y的地址>x的地址,说明栈是由高地址往低地址增长,而数据的写入是按低地址往高地址的顺序写入,所以,程序一旦没有对输入的数据做出限制,就会存在数据溢出当前栈的可能。
4.栈溢出(stack overflow),栈空间是有大小限制的,Linux系统可以用命令ulimit来查看,默认大小是8M。
堆区(Heap):
1.由程序员手动分配和释放的储存区
2.堆在内存中位于bss区和栈区之间
3.通过调用函数如malloc()、calloc()或realloc()来从堆中分配内存
4.必须手动调用free()函数来释放堆内存,否则可能导致内存泄漏
看下面的程序:
#include <stdio.h>
#include <stdlib.h>
int *create_array(int size)
{
int i;
int *p = (int *)malloc(size * sizeof(int));
if (p == NULL)
{
printf("malloc failed\n");
}
for ( i = 0; i < size; i++)
{
p[i] = 10 + i;
}
return p ;
}
int main(int argc, const char *argv[])
{
int i, n = 5;
int *p = create_array(n);
if (p == NULL)
{
return -1;
}
printf("p=%p\n", p);
for ( i = 0; i < n; i++)
{
printf("%d\n", *(p+i));
}
free(p);
p = NULL;
return 0;
}
第7行malloc申请堆空间,第25行调用函数,第39行free释放堆空间。
全局(静态)区:
1.内存分配在程序编译之前完成,且在程序的整个运行期间都存在
2.存储全局变量和静态变量
3.静态内存区细分还可以分成:.data段和.bss段
data段:初始化的全局变量、静态变量和只读数据都存放在这个域。
bss段:未初始化的全局变量和静态变量。
未初始化的变量,是在程序中说明,在运行的初始化阶段,才会真正占用存储空间,它的大小不会影响目标文件的大小。总结,一些变量放在bss段,可以减小目标文件的占用空间。
看下面的程序:
#include <stdio.h>
int globalVar = 10;//全局变量存储在静态存储区
void modifyGlobalVar(void)
{
static int count = 0;//静态变量也存储在静态存储区
globalVar = 20;//可以在函数中修改全局变量的值
}
int main(int argc, const char *argv[])
{
printf("Global variable:%d\n", globalVar);//输出全局变量的值
modifyGlobalVar();//调用函数修改全局变量的值
printf("Modified global variable:%d\n", globalVar);//输出修改后的全局变量的值
return 0;
}
常量区:
1.常量存储区用于存储常量数据,如字符串常量,const修饰的变量
2.常量存储区通常位于静态存储区内
看下面的程序:
#include <stdio.h>
int main(int argc, const char *argv[])
{
const int num = 10;//常量num存储在常量存储区
char *str = "hello";//字符串常量存储在常量存储区
printf("Constant variable:%d\n", num);//输出常量的值
printf("String constant:%s\n", str);//输出字符串常量的值
return 0;
}
代码区:
1.通常是用来存放程序执行代码的一块内存区域
2.该区域的大小在程序运行前就已经确定,并且内存区域通常属于只读