RTOS: 堆和栈

本文介绍了堆和栈两种内存管理方式。堆是手动分配和释放的内存,大小可变;栈由系统自动管理,保存局部变量,大小固定。通过示例代码展示了动态内存分配函数`my_malloc`的实现,并提供了调试堆内存变化的方法。同时,通过代码示例解释了栈在函数调用过程中的工作原理,强调了局部变量和返回地址的存储。建议在调试时关闭编译器优化以观察变量变化。
摘要由CSDN通过智能技术生成

堆和栈

概念

堆:程序员手动分配(malloc/new)和释放(free/java不用手动释放,由GC回收),在堆上分配内存叫动态分配,一般硬件内存有多大堆内存就有多大

栈:系统自动分配和释放,保存全局、静态、局部变量,在栈上分配内存叫静态分配,大小一般是固定的。

这里是才cubeMX模板上采用 韦东山 老师的demo,这里需要把MX_GPIO_Init()和HAL_Init()先屏蔽,要不然会一直进入硬件中断中。

/* USER CODE BEGIN 0 */
char heap_buf[1024];
int pos=0;

void *my_malloc(int size)
{
  int pre_pos=pos;
  pos += size;
  
  return &heap_buf[pre_pos];
}
/* USER CODE END 0 */
int main(void)
{
  /* USER CODE BEGIN 1 */
  char context = 'a';
  int size = 100;
  char *buf = my_malloc(size);
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  //HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  //SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  //MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
  for(int i=0; i<size; i++)
  {
    buf[i] = context;
  }
  
  /* USER CODE END 2 */
  return 0;
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

先设置为仿真环境,然后点击仿真的按钮,在对应的代码行加上断点就可以进行调试了
在这里插入图片描述
在这里插入图片描述
在调试过程中可以把对应变量添加到watch或者memory窗口进行查看
在这里插入图片描述
然后在单步运行的时候就可以看到对应的内存的变化,或者变量的变化了
在这里插入图片描述

使用下面的代码来看栈的过程

int a_func()
{
  int a=0;
  a++;
  return a;
}

int b_func()
{
  int b=0;
  b++;
  return b;
}

int c_func(int val)
{
  int c;
  c += val;
  
  a_func();
  b_func();
    
  
  return c;
}

int main(void)
{
  /* USER CODE BEGIN 1 */
  char context = 'a';
  int size = 100;
  char *buf = my_malloc(size);
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  //HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  //SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  //MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
  //for(int i=0; i<size; i++)
  {
   // buf[i] = context;
  }
  c_func(10);
  /* USER CODE END 2 */
  return 0;
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

在使用代码的时候,有可能无法打断点,这是因为编译器对代码进行了优化,可以在设置里面调整优化等级,这里设置为0(不做优化)就可以了。
在这里插入图片描述
这里借用韦东山老师的课堂笔记
在这里插入图片描述

每个函数在运行的时候都有自己的栈空间,来存储局部变量、LR(Link Register),LR用于保存子程序的返回地址,在调用函数的时候,会先lr压栈,在调用结束后根据lr在跳到对应的地址处(也就是调用子函数的下一句代码)

lr就是连接寄存器(Link Register, LR),在ARM体系结构中LR的特殊用途有两种:一是用来保存子程序返回地址;二是当异常发生时,LR中保存的值等于异常发生时PC的值减4(或者减2),因此在各种异常模式下可以根据LR的值返回到异常发生前的相应位置继续执行。

对应代码在这里 cubeMx heap-stck

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值