野指针:
指针变量中的值是非法的内存地址,进而形成野指针
野指针不是NULL指针,是指向不可用内存地址的指针
NULL指针并不危害,很好判断,也很好调试
指针所指向的变量在指针之前被销毁
使用已经释放过的指针
进行了错误的指针运算
进行了错误的强制类型转换
绝不返回局部变量和局部数组的地址
任何变量在定义后必须0初始化
字符数组必须确认0结束符后才能成为字符串
任何使用与内存操作相关的函数必须指定长度信息(确定长度信息相等)
指针变量中的值是非法的内存地址,进而形成野指针
野指针不是NULL指针,是指向不可用内存地址的指针
NULL指针并不危害,很好判断,也很好调试
C语言中无法判断一个指针所保存的地址是否合法
一个指针指向malloc申请的内存地址,其实指针是有效的,但是调用free后,这个地址将返还给内存,这个地址将不可用指针将变成野指针。
野指针的由来:
局部指针变量没有被初始化(指针变量定义的时候应该被初始化为NULL)指针所指向的变量在指针之前被销毁
使用已经释放过的指针
进行了错误的指针运算
进行了错误的强制类型转换
局部变量的地址和局部数组在函数调用之后就被摧毁,如果指针指向原来的变量或者数组,就会形成野指针
实例分析:
#include <stdio.h> #include <malloc.h> int main() { int* p1 = (int*)malloc(40); int* p2 = (int*)1234567; //错误的强制类型转换,但此时不会产生程序崩溃,取决的何时使用p2 int i = 0; for(i=0; i<40; i++) //指针运算产生野指针,改写了非法的内存地址 { *(p1 + i) = 40 - i; //出现越界:错误的指针运算。操作了没有申请的内存空间(非法的内存地址) } free(p1); //释放空间 但不负责将p1重置为空指针或者为任何的地址值 for(i=0; i<40; i++) { p1[i] = p2[i]; //段错误 使用已经释放过的指针 } return 0; }基本原则:
绝不返回局部变量和局部数组的地址
任何变量在定义后必须0初始化
字符数组必须确认0结束符后才能成为字符串
任何使用与内存操作相关的函数必须指定长度信息(确定长度信息相等)
#include <stdio.h> #include <string.h> #include <malloc.h> struct Student { char* name; //局部指针应初始化 int number; }; char* func() { char p[] = "D.T.Software"; return p; //返回一个局部数组 } void del(char* p) { printf("%s\n", p); free(p); } int main() { struct Student s; //未初始化指针,产生野指针 char* p = func(); //野指针 strcpy(s.name, p); //name也是野指针:s内的指针未初始化则为野指针。 使用了野指针 s.number = 99; p = (char*)malloc(5); strcpy(p, "D.T.Software"); //内存越界 :本质是对野指针进行了操作 del(p); return 0; }
可更改为:
struct Student { char* name; int number; }; char p[] = "D.T.Software"; char sp[] = "willwilling"; void del(char* p) { printf("%s\n", p); free(p); } int main() { struct Student s = {sp, 0}; char* pp = p; printf("p = %p\n", p); printf("pp = %p\n", pp); printf("pp = %s\n", pp); strcpy(s.name, pp); //s.name = pp; s.number = 99; pp = (char*)malloc(20); strcpy(pp, "D.T.Software"); del(pp); return 0; }