第一阶段12 C语言内存管理

加入CSDN是出于记录,希望有不足之处多加指正。

1、C进程的内存布局

  • 任何的C程序运行起来都需要一些内存资源,用来存放常量、变量、函数等资源。不同的资源内容会被存放到不同的内存区域中。不同的区域会有不同的特性。所以需要了解清楚各个区域的特性从而得知不同的资源有不同的特性。

  • 每一个程序运行起来后都会获得系统分配的一片虚拟内存。虚拟内存是从物理内存中映射得到的一个内存地址的取址范围。主要是为了方便软件开发人员开发软件,不需要考虑过多的物理内存的问题。假设直接使用物理内存,那么每个程序启动的先后顺序都会导致内存地址不确定,如果使用虚拟内存则不需要考虑该问题,因为每一个程序启动后都会获得一模一样的一片虚拟内存。
    PM:Physical Memory 物理内存
    VM:Virtual Memory 虚拟内存
    请添加图片描述

  • 查看CPU的信息可以获得虚拟内存与物理内存的取值:

gec@ubuntu:~$ cat /proc/cpuinfo
processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 158
model name	: *********************
stepping	: 10
microcode	: 0xb4
***************************************
bogomips	: 7200.01
clflush size	: 64
cache_alignment	: 64
address sizes	: 42 bits physical, 48 bits virtual
power management:

虚拟内存中的布局:

2、栈内存

栈内存中有什么:

  • 环境变量
  • 命令行参数
  • 局部变量(包括形参)

栈空间的特点:

  • 空间有限,尤其在嵌入式环境中。所以不推荐用来存放尺寸太大变量。
  • 每一个函数被调用,栈空间都会向下增长一段用来存放该函数的临时变量。
  • 每一个函数退出时,栈空间都会向上收缩一段,把该函数的所有局部变量的内存归还给系统(该段内存的值系统不一定会马上把他清空);
  • 栈内存的申请与释放用户都无法插手,都是由系统来完成。
#include <stdio.h>
int func (int x,int y);

int main(int argc, char const *argv[]) //程序运行会新的栈帧分配个main 来使用
{
    int a = 100,b = 200;
    func(a, b);  //程序运行到这里会产生一个新的栈帧,分配func 使用
                 // func函数退出,分配给他的栈帧,将会被系统回收,栈会向上收缩一段。
   
    return 0;  //main 退出,分配给main 的栈空间会被释放,系统回收
}

int func (int x,int y)  //产生一个新的栈帧,分配给func 使用
{
    int tmp = x;
     x = y;
     y = tmp;
     printf("a:%d ,b:%d\n",x , y);

     return 0;  //func 函数退出,分配给他的栈帧,将会被系统回收,栈会向上收缩一段
}

如何查看当前系统的栈内存限制:

gec@ubuntu:~/cyy$ ulimit -a

pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192      //当前系统默认的栈空间大小
cpu time               (seconds, -t) unlimited
max user processes              (-u) 3608
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

如何临时修改栈内存大小命令

$ ulimit -s 1024

3、数据段

什么是静态变量:

  • 全局变量:定义在函数体外的变量
  • 静态局部变量:定义在函数体内并且被static修饰的变量
#include <stdio.h>
    int a = 100;  //全局变量,跟程序的生命周期一致,用户中途无法释放
   
    int f(void)
  {
    int b =99;  //局部变量,当函数f被调用的时候出现并初始化为99,当函数f,退出时,b则被系统回收
    static int c = 199; //静态局部变量,当函数f 第一次被调用的时候会被定义并初始化为99,当函数f,被第二次调用的时候则不会被重新初始化,将维持上一次的值

    return 0;
  }
int main(void)
{
  f();
   
  return 0;
}

静态变量的作用

  • 全局变量在默认的情况下,对该程序中所有的函数甚至所有的文件都是可见的,为了方便某些资源在各个函数以及文件中共享而存在,算是最方便的一种共享资源的方法。
  • 当我们希望某个函数退出后的某个数值可以继续保留以便下次使用,就可以使用static 来修改该函数中的某个局部变量,换句话说就是把原本应该存放在栈空间的数据存放到数据段中,不需要跟着该函数共生死。

注意:

  • 未初始化的静态变量会被放置到 .bss段,程序运行时该段落的所有数据都会被初始化为0
  • 静态变量的初始化语句只会被执行一次
  • 静态变量在程序运行之初就已经存在直到程序退出才会被释放。
  • static 修饰局部变量,使得原本应该存放于栈中的数据,转为数据段,变成静态数据
  • static 修饰全局变量,使得该变量由原本的没有文件变成本文件可见。

3、堆内存

堆内存(heap)又被称为动态内存,自由内存。堆是唯一一个由用户自由发挥的区段,可以手动申请/释放/甚至大小。由于过于自由,很容易出现错误,对于何时申请,申请多大,何时释放等等一系列的问题就能体现一个程序员的登记了。

堆内存的特征:

  • 相对于栈来说堆的内存空间不受限制,唯一受到物理内存的限制。系统也不会限制堆内存的申请于释放。
  • 相对于栈内存来说堆内存的生长方式是自下而上
  • 堆内存都是匿名内存,只能通过指针来访问
  • 堆内存申请后除非开发者主动释放,否则永远存在,直到程序退出

4、堆内存相关的API

  • 申请堆内存: malloc / calloc / realloc
  • 清空内存: bzero / memset
  • 释放内存: free

malloc函数使用要求
这个函数要实现的功能是在系统中分配一段连续的
可用的内存,具体有如下要求:
1.malloc分配的内存大小至少为size参数所指定的
字节数.
2.malloc的返回值是一个指针,指向一段可用内存
的起始地址.
3.多次调用malloc所分配的地址不能有重叠部分,
除非某次malloc所分配的地址被释放掉.
4.malloc应该尽快完成内存分配并返回.
5.实现malloc时应同时实现内存大小调整和内存释
放函数(即realloc和free).

malloc (配置内存空间)
calloc (配置内存空间,并初始化为 0)
realloc (重新配置内存空间)
free (释放原先配置的内存)
头文件:#include <stdlib.h>
bzero (将一段内存内容全部清零)
memset (将一段内存空间填入某值)
头文件: #include <string.h>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值