# 踩内存检测<a name="ZH-CN_TOPIC_0000001124471131"></a>

-   [基础概念](#section17368154517335)
-   [功能配置](#section4696190123420)
-   [开发指导](#section672362973417)
    -   [开发流程](#section026014863416)
    -   [编程实例](#section186311302356)
    -   [示例代码](#section12709533354)
    -   [结果验证](#section81214126369)


## 基础概念<a name="section17368154517335"></a>

踩内存检测机制作为内核的可选功能，用于检测动态内存池的完整性。通过该机制，可以及时发现内存池是否发生了踩内存问题，并给出错误信息，便于及时发现系统问题，提高问题解决效率，降低问题定位成本。

## 功能配置<a name="section4696190123420"></a>

LOSCFG\_BASE\_MEM\_NODE\_INTEGRITY\_CHECK：开关宏，默认关闭；若打开这个功能，在target\_config.h中将这个宏定义为1。

1.  开启这个功能，每次申请内存，会实时检测内存池的完整性。
2.  如果不开启该功能，也可以调用LOS\_MemIntegrityCheck接口检测，但是每次申请内存时，不会实时检测内存完整性，而且由于节点头没有魔鬼数字（开启时才有，省内存），检测的准确性也会相应降低，但对于系统的性能没有影响，故根据实际情况开关该功能。

由于该功能只会检测出哪个内存节点被破坏了，并给出前节点信息（因为内存分布是连续的，当前节点最有可能被前节点破坏）。如果要进一步确认前节点在哪里申请的，需开启内存泄漏检测功能，通过LR记录，辅助定位。

>![](public_sys-resources/icon-caution.gif) **注意：** 
>开启该功能，节点头多了魔鬼数字字段，会增大节点头大小。由于实时检测完整性，故性能影响较大；若性能敏感的场景，可以不开启该功能，使用LOS\_MemIntegrityCheck接口检测。

## 开发指导<a name="section672362973417"></a>

### 开发流程<a name="section026014863416"></a>

通过调用LOS\_MemIntegrityCheck接口检测内存池是否发生了踩内存，如果没有踩内存问题，那么接口返回0且没有log输出；如果存在踩内存问题，那么会输出相关log，详见下文编程实例的结果输出。

### 编程实例<a name="section186311302356"></a>

本实例实现如下功能：

1.  申请两个物理上连续的内存块；
2.  通过memset构造越界访问，踩到下个节点的头4个字节；
3.  调用LOS\_MemIntegrityCheck检测是否发生踩内存。

### 示例代码<a name="section12709533354"></a>

代码实现如下：

```
#include <stdio.h>
#include <string.h>
#include "los_memory.h"
#include "los_config.h"

void MemIntegrityTest(void)
{
    /* 申请两个物理连续的内存块 */
    void *ptr1 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8);
    void *ptr2 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8);
    /* 第一个节点内存块大小是8字节，那么12字节的清零，会踩到第二个内存节点的节点头，构造踩内存场景 */
    memset(ptr1, 0, 8 + 4);
    LOS_MemIntegrityCheck(LOSCFG_SYS_HEAP_ADDR);
}
```

### 结果验证<a name="section81214126369"></a>

编译运行输出log如下：

```
[ERR][OsMemMagicCheckPrint], 2028, memory check error!
memory used but magic num wrong, magic num = 0x00000000   /* 提示信息，检测到哪个字段被破坏了，用例构造了将下个节点的头4个字节清零，即魔鬼数字字段 */

 broken node head: 0x20003af0  0x00000000  0x80000020, prev node head: 0x20002ad4  0xabcddcba  0x80000020   
/* 被破坏节点和其前节点关键字段信息，分别为其前节点地址、节点的魔鬼数字、节点的sizeAndFlag；可以看出被破坏节点的魔鬼数字字段被清零，符合用例场景 */

 broken node head LR info:  /* 节点的LR信息需要开启内存检测功能才有有效输出 */
 LR[0]:0x0800414e
 LR[1]:0x08000cc2
 LR[2]:0x00000000

 pre node head LR info:   /* 通过LR信息，可以在汇编文件中查找前节点是哪里申请，然后排查其使用的准确性 */
 LR[0]:0x08004144
 LR[1]:0x08000cc2
 LR[2]:0x00000000
[ERR]Memory interity check error, cur node: 0x20003b10, pre node: 0x20003af0   /* 被破坏节点和其前节点的地址 */
```

