diff --git a/rt-thread-version/rt-thread-standard/programming-manual/memory/memory.md b/rt-thread-version/rt-thread-standard/programming-manual/memory/memory.md index c7d190c37ebfec17ed91ce96fe316cda72dc15c5..dcb3ef1b063201c149eca93977284ea7c164d832 100644 --- a/rt-thread-version/rt-thread-standard/programming-manual/memory/memory.md +++ b/rt-thread-version/rt-thread-standard/programming-manual/memory/memory.md @@ -161,7 +161,20 @@ rt_malloc 函数会从系统堆空间中找到合适大小的内存块,然后 | 分配的内存块地址 | 成功 | | RT_NULL | 失败 | -应用程序使用完从内存分配器中申请的内存后,必须及时释放,否则会造成内存泄漏,释放内存块的函数接口如下: +对 rt_malloc 的返回值进行判空是非常有必要的。应用程序使用完从内存分配器中申请的内存后,必须及时释放,否则会造成内存泄漏。 + +使用动态分配内存示例: + +```c +int *pi; +pi = rt_malloc(100); +if(pi == NULL) +{ + rt_printf("malloc failed\r\n"); +} +``` + +释放内存块的函数接口如下: ```c void rt_free (void *ptr); @@ -175,6 +188,10 @@ rt_free 函数会把待释放的内存还回给堆管理器中。在调用这个 |----------|--------------------| | ptr | 待释放的内存块指针 | +rt_free 的参数必须是以下其一: +- 是 NULL 。 +- 是一个先前从 rt_malloc、 rt_calloc 或 rt_realloc 返回的值。 + #### 重分配内存块 在已分配内存块的基础上重新分配内存块的大小(增加或缩小),可以通过下面的函数接口完成: @@ -194,6 +211,10 @@ void *rt_realloc(void *rmem, rt_size_t newsize); |**返回** | —— | | 重新分配的内存块地址 | 成功 | +- rt_realloc 函数用于修改一个原先已经分配的内存块的大小。使用这个函数,你可以使一块内存扩大或者缩小。如果它用于扩大一个内存块,那么这块内存原先的内容依然保留,新增加的内存添加到原先内存块的后面,新内存并未以任何方式进行初始化。如果它用于缩小一个内存块,该内存尾部的部分内存便被拿掉,剩余部分内存的原先内容依然保留。 +- 如果原先的内存块无法改变大小,rt_realloc 将分配另一块正确大小的内存,并把原先那块内存的内容复制到新的块上。因此,在使用 rt_realloc 之后,你就不能再使用指向旧内存块的指针,而是应该改用 rt_realloc 所返回的新指针。 +- 如果 rt_realloc 的第一个参数为 NULL, 那么它的行为就和 rt_malloc 一样。 + #### 分配多内存块 从内存堆中分配连续内存地址的多个内存块,可以通过下面的函数接口完成: @@ -273,6 +294,26 @@ void hook(void *ptr); |----------|--------------------| | ptr | 待释放的内存块指针 | +### 总结 + +动态内存使用总结: + +- 检查从 rt_malloc 函数返回的指针是否为 NULL +- 不要访问动态分配内存之外的内存 +- 不要向 rt_free 传递一个并非由 rt_malloc 函数返回的指针 +- 在释放动态内存之后不要再访问它 +- 使用 sizeof 计算数据类型的长度,提高程序的可移植性 + +常见的动态内存错误: + +- 对 NULL 指针进行解引用 +- 对分配的内存进行操作时越过边界 +- 释放并非动态分配的内存 +- 释放一块动态分配的内存的一部分 (rt_free(ptr + 4)) +- 动态内存被释放后继续使用 + +内存碎片:频繁的调用内存分配和释放接口会导致内存碎片,一个避免内存碎片的策略是使用 `内存池 + 内存堆` 混用的方法。 + ### 内存堆管理应用示例 这是一个内存堆的应用示例,这个程序会创建一个动态的线程,这个线程会动态申请内存并释放,每次申请更大的内存,当申请不到的时候就结束,如下代码所示: