【编程基础】--进程内存分配

1 篇文章 0 订阅
本文详细解释了程序运行时的内存管理,包括进程的概念、内存中的不同存储段(栈、堆、BSS、data、text和rodata)的作用,以及字符串常量、数组和指针在内存中的存储特点。特别关注了未初始化变量的BSS段和初始化变量的data段的区别,以及静态变量的生命周期变化。
摘要由CSDN通过智能技术生成

  我们平常写的程序,要想运行必须是要借助真实的物理空间(内存),每一个程序至少是有一个进程,因为操作系统中进程是资源分配的基本单位,程序的中的各种变量,还有代码段,在我们内存中按照指定的方式进程存储可以分为堆,栈,bss,data,text,rodata,常量段。

存储段作用性质
存放程序运行时,临时创建的局部变量,在函数被调用时,函数的参数和函数内部变量压栈,调用结束后,出栈。RW
存放程序运行时,动态分配的内存段,malloc.free函数RW
bss存放程序中未初始化的全局变量,只是一个占位符并不占据内存空间RW
data存放程序中已经初始化的全局变量和静态变量(static修饰)RW
text存放程序执行代码和一些常量,如字符串常量,define定义R

size 查看文件大小
text和data段的内容存在与磁盘中;
bass段存放的是变量的名字和大小,变量并不实际存在于磁盘中;
堆和栈由程序运行时分配。
在这里插入图片描述

在这里插入图片描述

1.关于bss和data存放的数据的思考(原文
有两段代码:
程序A

int ar[30000];
void main()
{

}

程序B

int ar[300000] =  {1, 2, 3, 4, 5, 6 };
void main()
{
    ......
}

会发现程序B编译后得到的exe运行文件,比程序A大。

因为:A中的arr变量未初始化,存在bss段中,B中的arr初始化了存在与data段中, .bss是不占用.exe文件空间的,具体体现为一个占位符data却需要占用,其内容由程序初始化。

bss段并不给该段的数据分配空间,只是记录数据所需空间的大小, BSS段的大小从可执行文件中得到,然后链接器得到这个大小的内存块,紧跟在数据段后面。当这个内存区进入程序的地址空间后全部清零。包含DATA和BSS段的整个区段此时通常称为数据区。
2.关于字符串常量的思考(原文
字符串常量位于text段,只能读,对于以数组定义字符串和指针定义字符串就有了区别。

//数组定义
char str[] = "hello, world";
str[1] = 'a';          //可以
str++;                //不可以 

//指针定义
char *str = "hello, world";
str[1] = 'a';         //不可以
str++;                //可以 

原因是:
使用数组名时,数组名是隐式被const修饰的指针,一个常量指针,其指向的地址不能修改。
使用指针时 “hello, world” 是一个字符串常量,str 的确指向其地址,但该地址存在于在进程的 text 段,不可以改变其中的内容。

同时对于char * 与char[] (链接)
1.char指向的区域有时可写,有时只读。
2.char * a=”string1”;是实现了3个操作:
  1声明一个char
变量(也就是声明了一个指向char的指针变量)。
  2在内存中的文字常量区中开辟了一个空间存储字符串常量”string1”。
  3返回这个区域的地址,作为值,赋给这个字符指针变量a
  最终的结果:指针变量a指向了这一个字符串常量“string1”
  ******如果这时候再执行:char * c=”string1”;则,c==a,
  ******只会执行上述步骤的1和3,因为这个常量已经在内存中创建
3.char b[]=”string2”;则是实现了2个操作:
  1声明一个char 的数组,
  2为该数组“赋值”,将”string2”的每一个字符分别赋值给数组的每一个元素,存储在栈上。
  最终的结果:“数组的值”(注意不是b的值)等于”string2”,而不是b指向一个字符串常量
4.函数形参中,数组退化成指针,所以传递的形参数组大小可以不为实参的大小
  (sizeof()占用字节的多少,strlen()字符串从开头到‘\0’的长度)

/*
char * a=”string1”; 的写法是不规范的
*/
char * a="string";
char b[]="string2";
strcpy(a,"string2"); //错误 因为a指向的是text段的内存,只能读
a = b;
strcpy(a,"string2"); //可以 因为a指向的是栈区的内存,可读可写
/*
"Hello World"字符串常量,位于text段
char *a ;char b[]位于栈区
a指向的地址是text段的地址,a本身的地址是栈区地址
b指向的地址是栈区的地址 = b本身的地址是栈区地址
*/
char *a="Hello World";
char b[]="Hello World";
printf("%s, %d\n","Hello World", "Hello World");  //Hello World 13457308
printf(%s, %d %d\n”, a, a, &a);//Hello World 13457308 2030336
printf(%s, %d %d\n”, b, b, &b);//Hello World 2030316 2030316
void Foo(char strOutSide[128])
{
void* p = malloc(256);
char strInside[128];
int output = sizeof(p) + sizeof(strOutSide) + sizeof(strInside);
print(output);
}
/*
函数里面的数组名退化成指针(所以传递的形参数组可以不为128),最后是8+8+128
*/

3.局部变量被static修饰后,寿命周期改变

原因式static修饰的变量存储在data段,不会和函数中其它变量一样,函数退出后出栈。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值