主题五 内存管理的艺术----32.头疼的野指针
来源:互联网 发布:22lr子弹淘宝 编辑:程序博客网 时间:2024/05/29 04:30
什么是野指针?
野指针通常是因为指针变量中保存的值不是一个合法的内存地址而造成的(合法的内存地址有2种:堆空间和栈空间)
野指针不是NULL指针,是指向不可用内存的指针。
NULL指针不容易用错,因为if语句很容易判断一个指针是不是NULL。
C语言中没有任何手段可以判断一个指针是否为野指针!(只有运行到野指针时才能发现异常,但是原因,具体错误代码还是不可知)。
野指针的3种根源:
1.局部指针变量没有初始化,指向不确定的内存地址(可能被系统,其它程序占用,或者巧合没有程序占用)
#include <stdio.h>#include <string.h>struct Student{ char* name; int number;};int main(){ struct Student s; strcpy(s.name, "Delphi Tang"); // OOPS! 局部变量没有初始化 s.number = 99; return 0;}
2.使用已经释放了的指针
#include <stdio.h>#include <malloc.h>#include <string.h>void func(char* p){ printf("%s\n", p); free(p);}int main(){ char* s = (char*)malloc(5); strcpy(s, "Delphi Tang"); //内存越界 func(s); printf("%s\n", s); // OOPS! return 0;}
3.指针所指向的变量在指针使用前被销毁
#include <stdio.h>char* func(){ char p[] = "Delphi Tang"; return p;}int main(){ char* s = func(); printf("%s\n", s); // OOPS! return 0;}
经典错误再现(非法内存操作分析)
1.结构体成员指针未初始化
2.没有未结构体指针分配足够的内存
#include <stdio.h>#include <malloc.h>struct Demo{ int* p;};int main(){ struct Demo d1; struct Demo d2; int i = 0; for(i=0; i<10; i++) { d1.p[i] = 0; // OOPS! } d2.p = (int*)calloc(5, sizeof(int)); for(i=0; i<10; i++) { d2.p[i] = i; // OOPS!内存越界,修改了其它部分的逻辑,错误根源难以追查。 } free(d2.p); return 0;}
3.内存初始化错误:(例:内存分配成功,但并未初始化)
include <stdio.h>#include <malloc.h>int main(){ char* s = (char*)malloc(10); printf(s); // OOPS! free(s); return 0;}
4.内存越界错误:(例:数组越界)
#include <stdio.h>void f(int a[10]){ int i = 0; for(i=0; i<10; i++) { a[i] = i; // OOPS! printf("%d\n", a[i]); }}int main(){ int a[5]; f(a); return 0;}
5.内存泄漏错误
#include <stdio.h>#include <malloc.h>void f(unsigned int size){ int* p = (int*)malloc(size*sizeof(int)); int i = 0; if( size % 2 != 0 ) { return; // OOPS!函数单入口双出口,其中一个存在内存泄漏,开发函数最好单入口单出口 } for(i=0; i<size; i++) { p[i] = i; printf("%d\n", p[i]); } free(p);}int main(){ f(9); f(10); return 0;}
6.多次指针释放
#include <stdio.h>#include <malloc.h>void f(int* p, int size){ int i = 0; for(i=0; i<size; i++) { p[i] = i; printf("%d\n", p[i]); } free(p);}int main(){ int* p = (int*)malloc(5 * sizeof(int)); f(p, 5); free(p); // OOPS!Aborted!自作多情,特别是调用其它人提供的函数,好习惯:谁申请谁释放 return 0;}
7.使用已经释放的指针
#include <stdio.h>#include <malloc.h>void f(int* p, int size){ int i = 0; for(i=0; i<size; i++) { printf("%d\n", p[i]); } free(p);}int main(){ int* p = (int*)malloc(5 * sizeof(int)); int i = 0; f(p, 5); for(i=0; i<5; i++) { p[i] = i; // OOPS! } return 0;}
阅读全文
0 0
- 主题五 内存管理的艺术----32.头疼的野指针
- 主题五 内存管理的艺术----29.动态内存的分配
- 主题五 内存管理的艺术----30.内存中的三雄并立
- 主题五 内存管理的艺术----31.程序文件的一般布局
- 专题五-内存管理的艺术
- 内存管理的艺术
- 头疼的指针
- C语言内存管理的艺术
- 头疼,不停的头疼.
- 指针的意义和linux的内存回收艺术
- 指针的艺术
- 指针的艺术
- 指针的艺术
- 指针的艺术
- 指针的艺术
- 指针的艺术
- 指针的艺术
- 指针的艺术
- ubuntu16.04LTS更换阿里源
- ASP.NET MVC4中@model使用多个类型实例的方法
- Thinking in java-8 单继承和多态
- 魔术2
- 51单片机学习第三天
- 主题五 内存管理的艺术----32.头疼的野指针
- Working with form fields---1
- Python规范
- 虚树
- 6.18-Python-语言及其应用-笔记-像高手一样玩转数据-未完!
- 流畅的python--字典中的散列表
- binding之component
- angularjs-依赖注入:显示注入和隐式注入
- 【机器学习算法模型】分类决策树——CART