野指针
定义:指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)
一、野指针的成因
1、指针未初始化
#include <stdio.h>
int main(void) {
// 定义一个未初始化的指针并赋值
int* p;
*p = 5;
// 打印输出指针的值
printf("%d", *p);
return 0;
}
结果出现了断错误,而段错误产生的原因就是因为指针p没有分配给它内存,没有明确的指向。
修改方式如下:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
// 定义一个指针并给它分配内存地址
int* p = malloc(sizeof(int));
*p = 5;
// 打印输出指针的值
printf("%d", *p);
return 0;
}
结果为5,避免了指针未初始化错误导致的野指针错误
2、指针的越界访问
// 指针越界访问
#include <stdio.h>
int main() {
int arr[5] = {0};
int *p = arr;
for(int i = 0; i < 7; i++) {
*(p++) = i;
printf("%d", *p);
}
return 0;
}
使用gdb调试时,会发现在前5次中都没发送错误,证明前五次中并不属于野指针,在第六次后发送了野指针错误。
该错误避免方法就是注意指针指向的位置是否越界,小心一点即可。
3、指针指向空间被释放
// 指针指向空间被释放
#include <stdio.h>
int* test() {
int a = 20;
return &a;
}
int main() {
// 定义指针
int *p = test();
printf("%d", *p);
return 0;
}
运行后发现,也会出现段错误,这仅仅是因为在创建指针后,它所指向的位置空间已经被释放了
看上述代码,很容易发现,调用test时有一个临时变量a,而该函数返回的就是a所在的地址。但是当test调用结束后,此时a已经被释放,所以此时的p为野指针。
二、野指针的避免
1. 指针初始化(防止野指针成因1)
2. 小心指针越界(防止野指针成因2)3. 避免返回局部变量的地址(防止野指针成因3)
4. 指针指向空间释放即使置NULL(只是一个好习惯,可以在使用指针后判断是否为NULL来判断该指针是否释放过了)
5. 指针使用之前检查有效性(即4之后的步骤)