
目录1. 栈区Stack存什么栈的特点1自动管理2空间较小2. 堆区Heap存什么堆的特点1需要手动释放3. 静态区4.内存泄漏1. 申请后忘记释放最常见2. 指针被覆盖丢失原地址3. 直接把指针改成 NULL4. 链表删除结点忘记 free5.野指针Dangling Pointerfree之后产生野指针最常见程序运行时内存通常会划分成几个区域其中最常讲的是高地址 ┌─────────────┐ │ 栈区 │ ← 局部变量、函数调用 ├─────────────┤ │ 堆区 │ ← 动态申请的内存 ├─────────────┤ │ 全局/静态区 │ ← 全局变量、static变量 ├─────────────┤ │ 代码区 │ ← 程序指令 └─────────────┘ 低地址1. 栈区Stack存什么函数的局部变量函数参数临时变量指针变量本身例如void test() { int a 10; Node *front; }内存栈区 地址500: a 10 地址600: front ?这里a在栈里front这个指针变量也在栈里栈的特点1自动管理例如void test() { int a; }执行进入函数 ↓ 创建a 函数结束 ↓ a自动消失不需要free(a); // 错误2空间较小栈通常有限。例如递归void fun() { fun(); }无限调用fun() ↓ fun() ↓ fun() ↓ ...最后栈空间耗尽 Stack Overflow2. 堆区Heap存什么存程序运行时动态申请的内存。例如Node *p; p malloc(sizeof(Node));堆的特点1需要手动释放申请p malloc(sizeof(Node));释放free(p);否则堆里的内存一直占用这就是内存泄漏3. 静态区静态区是一定占内存的只是它和栈、堆不一样它是程序一启动就分配好一直到程序结束才释放。4.内存泄漏内存泄漏 在堆区申请了一块动态内存但是程序后来再也找不到它也没有释放它。关键词有两个堆区内存malloc申请的丢失了释放它的机会1. 申请后忘记释放最常见函数结束后p这个指针变量栈区会自动释放但是p指向的Node空间堆区不会自动释放如果没有free就会造成内存泄漏。Node *p malloc(sizeof(Node));如果没有free(p);函数结束后栈 p 消失 堆 Node还在→内存泄漏2. 指针被覆盖丢失原地址p malloc(sizeof(Node)); // 地址1000 p malloc(sizeof(Node)); // 地址2000结果p → 2000 1000的内存没人指向→泄漏3. 直接把指针改成 NULLp malloc(sizeof(Node)); p NULL;结果p → NULL 原来的堆内存找不到了→泄漏正确free(p); p NULL;4. 链表删除结点忘记 free错误front front-next;原front ↓ A → B → C变front ↓ B → C A丢失A 还占内存。→泄漏正确p front; front front-next; free(p);5.野指针Dangling Pointer野指针 指针变量保存了一个地址但是这个地址对应的内存已经无效。简单说指针还活着但它指向的东西没了。free之后产生野指针最常见代码Node *p malloc(sizeof(Node)); free(p);执行free(p);free(p)之后p里面保存的地址值还可能保持不变但这个地址对应的内存已经不再属于你的程序p再去访问它就是非法的。注意p变量还存在p里面的地址还保存着1000但是1000那块内存已经不能用了。此时*p 10; // 错误因为你访问的是已经释放的空间这时 p 就是野指针free(p)不会主动把 p 改成 NULL大多数情况下 p 仍然保存原地址但标准不保证所以严谨说“可能”。在编程习惯上把它当作“已经失效”处理。