野指针概念:
如果一个指针指向的内存没有访问权限,或者指向一块已经废弃掉的内存,那么就无法对该指针进行操作,这就是野指针。
1.指向没有访问权限的内存:
#include <stdio.h>
int main()
{
char *s;
gets(s); //从流中读取字符串,碰到文件末尾或者\n时结束。
puts(s); //字符串标准输出stdout,直到空字符,但是输出里面不包含空字符,包含\n
return 0;
}
这段程序在GCC下运行会报Segment Fault错误,因为s是局部指针变量,其值是随机不确定的,不知指向哪块内存。一般情况下这种内存要么不能访问,要么是没有分配的。
但是也有极低的概率会指向一个分配好的内存地址,虽是暂时程序没崩溃,但是碰到的概率是极低的。
2.指向释放掉的内存:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *s = (char*)malloc(sizeof(char)*18); //向系统申请char类型长度的18个元素大小的堆内存
strcpy(s, "my name is hornets");
puts(s);
free(s); //释放内存
if (s)
{
puts(s);
}
return 0;
}
第一次puts会输出“my name is hornets”, 第二次就会乱码或者啥也不输出,因为第一次输出之后释放掉内存了,但是指针s的值并没有变,也就是说指向的位置没有变,所以第二次puts时指针s指向了一个被释放掉的内存,原来的字符串不存在了, 所以输出的数据是未知的, 这种指针也叫做悬空指针。
所以若碰到这种需求,释放掉内存之后必须把所有指向该内存的指针的值都设为NULL。
还有一种情况是函数外的指针访问函数内的变量 数组,在c/c++内存精讲里面我提到过,函数里的变量 数组是在栈上分配内存,栈是操作系统自动分配释放的,无需程序员自己手动此操作,所以当函数运行结束之后,函数里的数组或者变量就被释放了,所以函数外的指针指向的也是被释放掉的内存。
3.避免野指针:
-
指针变量暂且不需要赋值的话,初始化为NULL,因为指针不会自动赋值NULL,他的缺省值是随机的。
-
当指针变量指向的内存被释放后,要将指针赋值为NULL。因为free()之后只是释放了内存,并未改变指针的值。
不要相信网上有些博客说野指针很恐怖,没有初始值的话就会有概率指向别的程序的值,从而会导致别的程序崩溃。这种说法是过时的,这是1998年VC6时的标准,哈哈哈哈。
原因是因为现在的系统都有内存保护,上节内存精讲里面我也说到过,用户进程拿到的都是虚拟地址,并不会影响别的程序内存,顶多会崩溃自己的程序而已,野指针并不是最可怕,而是需要保持自己良好的编程习惯。
不小心写出了野指针, 不要说出来, 不要改, 自己默默记住位置. 这就是你下个月奖金的来源.
原文链接: https://www.cnblogs.com/hornets/p/12489330.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;
也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/335074
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!