ARM架构与FreeRTOS中的内存管理(flash与SRAM,堆栈)-优快云博客
栈顶指的是当前栈指针(Stack Pointer, SP)所指向的内存地址。栈底指的是栈的起始地址,也就是栈区域在内存中的最低地址。在一个空栈中,栈顶是没有元素的,通常被定义为 -1 或 NULL。
对比看指针,当我们定义一个指针变量的时候,初值一定要将他赋成NULL,明确指针没有指向任何有效的内存地址,如果未初始化指针变量,指针变量会指向一个随机的内存地址,这个地址可以是一个已经被使用的地址,如果试图通过这个指针访问或操作这个内存区域,可能会导致程序崩溃,出现段错误(Segmentation Fault)。指针变量的起始地址就是栈底的地址。栈指针(SP)的变化,反映了指针变量在栈上的位置变化。
关于MCU的内存与指针,数组,函数的关系与操作:
第一,指针保存的是MCU的内存单元的地址,通过指针操作内存,如果第一次定义, 那么int *ptr 就代表这个地址,如果第一次是 int *ptr = NULL;那么接下来 ptr 就代表这个指针的地址。如果我定义了一个指针 *ptr,要想获取这个指针变量的地址就要用 &ptr,要想获取这个指针变量的数据就要用 *ptr,这里的”*“代表的是解引,与我们第一次定义的指针变量的“ * ”不是一个含义。
如果我想让指针变量 *ptr 指向变量 value 在内存中的地址,需要用 int *ptr = &value,因为指针 int *ptr 代表的是物理地址(如果是A核就是逻辑地址,MCU一般没有MMU就是物理地址),或者int *ptr = NULL;ptr = &value
第二,在代码中定义一个数组,数组第一个元素的地址就是整个数组在内存中的起始地址,数组的各个元素在内存中是连续存放的,如果想知道数组的地址,用取地址运算符&来获取数组元素的地址,例如&array[i]可以得到数组第i个元素的地址,array[i] 获取的是数组中的数据。如果用指针访问数组,那就是说要将我们定义的指针变量的地址指向数组的起始地址,也就是 int *ptr = &arr[0] 或 int *ptr = arr。
第三,指针函数与函数指针
指针函数:是一个返回指针类型的函数,比如:int *get_max(int a, int b) { return &a; } ,他的返回值是一个地址,
函数指针:是一个指向函数的指针变量,比如:int (*ptr_max)(int, int) = get_max; 相当于用函数指针调用指针函数,也就是将指针函数返回的地址赋值给函数指针,也就相当于int (*ptr_max)(int, int) 变成了一个指针变量,相当于 int *ptr_Value = ptr_max(a, b); 或者 int *ptr_Value = NULL; ptr_Value = ptr_max(a, b);
一般在MCU中使用指针函数与函数指针的情况是在“回调函数”,“数据结构和算法”等。
举例回调函数,理解实现意图,用数组举例说明
定义一个数组,
数组的起始地址传递给指针变量
将指针变量当成数组用,获取当中的数据
举例指针函数
野指针常见的产生原因:
- 指针变量初值没有赋成NULL。
- 当函数返回时,它的堆栈会被销毁,其中的局部变量也就不再有效。但如果在函数外部还持有一个指向该局部变量的指针,它就会变成野指针。
- 如果通过指针访问数组元素时,下标越界访问了数组之外的内存,也会产生野指针。
- 当一个动态分配的内存块被释放(free)后,指向该内存块的指针就变成了野指针。
堆栈溢出常见的产生原因:
堆栈溢出相当于数组越界,栈内存用于存储函数调用的上下文信息和局部变量。
- 局部变量占用过多内存,超出任务定义的堆栈大小。
- 递归(递归调用就是一个函数在自己内部再次调用自己)调用深度过深或函数调用层次过深。
- 函数没有返回,没有 return 语句意味着函数无法主动返回,它创建的栈帧也无法被正常销毁,函数的栈帧会不断增加,造成栈空间耗尽,最终导致栈溢出(Stack Overflow)错误。
- 无限循环,每次循环都会在栈上压入新的栈帧。
内存泄漏常见的产生原因:
【C语言】你对动态内存分配有多少了解呢_什么是动态内存分配-优快云博客
内存泄漏是指程序在动态分配内存后,没有在适当的时候释放或销毁这些内存,导致内存被占用但无法再次利用的情况。随着程序运行时间的增长,被泄漏的内存会越来越多,直到耗尽系统的所有可用内存,从而导致程序崩溃或严重性能下降。内存泄漏通常发生在堆内存中,而不是栈内存中。
- 程序动态分配内存后,忘记在合适的时候释放或销毁这些内存空间。
- 复杂的数据结构(如链表、哈希表等)中,如果在删除元素时忘记清理相关引用,也会导致内存泄漏。
FreeRTOS 提供了功能和机制来帮助管理和检测内存泄漏,钩子函数(Hooks),内存保护(MPU),内存泄漏检测(Memory Leak Detection),内存状态跟踪(Memory Status Tracking)