一、简述堆栈

栈(Stack): 由编译器自动分配释放
堆(heap): 一般由程序员分配和释放

在这里插入代码片
int b;  // 栈
char s[] = "abc"; 	//栈
char *p2;			//栈
p1 = (char*)malloc(10); //堆
p2 = (char*)malloc(20); //堆

二、STM32中的栈和堆如何设置大小

以RTthread官方的STM32F103XE为例:在启动文件有如下定义

堆区和栈区的大小在如下位置定义,可以按自己的需要修改,注意单片的RAM的大小,堆和栈不是你想改多大就多的。

arthas 有java线程 但是 识别不了_c语言

三、RT-Thread使用动态内存

3.1 初始化

arthas 有java线程 但是 识别不了_c语言_02


这时,rt-thread就开启了动态管理的功能,初始化代码如下:

arthas 有java线程 但是 识别不了_动态内存_03


该代码赋予了rt-thread管理动态内存(堆)的权限。

其中,HEAP_BEGIN定义:

#define HEAP_BEGIN  ((void *)&Image$$RW_IRAM1$$ZI$$Limit)

其中:

Image$$RW_IRAM1$$ZI$$Limit

是一个链接器导出的符号,代表ZI段的结束,也就是程序执行区的RAM结束后的地址,反过来也就是我们执行区的RAM未使用的区域的起始地址,将这一部分作为我们OS管理的堆的起始地址。

HEAP_END定义:

#define HEAP_END    STM32_SRAM_END
#define STM32_SRAM_END (0x20000000 + STM32_SRAM_SIZE * 1024) //0x20000000为该单片机内部RAM的            
                                                             //起始地址
#define STM32_SRAM_SIZE 64 //该单片机的RAM为64K

也就是说HEAP_END就是该单片机的RAM的结束地址。

总结一下,这个初始化函数就是将地址从HEAP_BEGIN到HEAP_END之间的空间作为OS管理的堆空间。

3.2 rt-thread使用动态内存的API
1、获取动态内存:

void *rt_malloc(rt_size_t size)

入口参数为字节数,失败则返回RT_NULL,最好使用类似如下的语句判断是否获取内存成功:

/* 分配 512字节数的内存空间 */
        ptr = rt_malloc(512);
 
        /* 如果分配成功 */
        if (ptr != RT_NULL)
        {
           //此处使用ptr
        }

2、释放获取的内存:

void rt_free(void *rmem)
 
rt_free(ptr); //使用举例,对应上文

入口参数为要释放的空间的指针,切记,分配了就要要对应的释放,否则会造成内存泄露,甚至系统崩溃。

3、动态内存堆使用注意
(1)、内存复位

每次新申请的内存块,建议对内存块进行清零操作(因为之前的内存块可能被分配存在一些无意义的数据),使用如下操作:

rt_memset(ptr,0,512); //ptr对应上文已分配内存的指针

(2)、内存泄露

分配的内存使用完后要及时清理,rt_malloc和rt_free要成双成对使用。内存泄露后果严重,轻则造成系统变得缓慢,重则造成系统崩溃。

代码调试部分:

arthas 有java线程 但是 识别不了_动态内存_04


arthas 有java线程 但是 识别不了_#define_05


arthas 有java线程 但是 识别不了_嵌入式硬件_06


将下列代码写入调试串口:

arthas 有java线程 但是 识别不了_c语言_07


arthas 有java线程 但是 识别不了_动态内存_08


允行即可调试完成!!!