1、什么是野指针
指向不可用或者不应该被使用的内存的指针(注意,不是NULL指针)
2、产生野指针的原因
1、指针变量没有初始化。属于栈区的变量没有初始化,如果没有初始化,值是不确定的。也就是说,没有被初始化的指针,指向的是不应该被使用的内存,如果使用了该内存,会产生不可知的错误。
#include<stdio.h>
int main()
{
int *p;
printf("%p\n",p);
*p = 10;
printf("%d\n", *p);
return 0;
}
2、指向堆区的指针被free()后,没有置为NULL。free()函数是把指针所指向的内存区域释放,使得该区域成为自由内存,可以被再次分配。但是,函数并没有把指针本身的内容置空,指针仍然指向已经被释放的堆内存。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *p = malloc(sizeof(int));
if(!p){
printf("malloc error\n");
exit(1);
}
printf("p:%p\n",p);
*p = 10;
printf("*p:%d\n", *p);
free(p);
printf("p:%p\n",p);//p指针本身的值还是free()之前的值
printf("*p:%d\n", *p);//该内存在没有被再次被分配重新赋值之前还是原来的值
int *i = malloc(sizeof(int));
if(!i){
printf("malloc error\n");
exit(1);
}
printf("i:%p\n",i);//该内存区域被释放,可以被再次分配
*i = 20;
printf("*i:%d\n", *i);
*p = 10;
printf("*i:%d\n", *i);//i指针指向的内存区域被p指针修改了,但这是不应该发生的
free(i);
i = NULL;
P = NULL;
return 0;
}
3、指针操作越界。C语言不做越界检查,所以由于程序逻辑上的错误,导致指针访问了不应该访问的内存。常见的是数组越界。
#include<stdio.h>
int main()
{
int arr[5] = {1,2,3,4,5};
for(int i = 0; i <= 5; ++i)
{
printf("%d\t",arr[i]);
}
printf("\n");
}
4、指针函数返回指向栈内存的指针。函数指针会返回一个指针,然后在主调函数中使用该指针指向的内存。因此,指针函数不能返回在该函数内指向栈内存的指针,因为栈区是由程序自动释放。
#include<stdio.h>
int *add(int a,int b){
int *sum ;
*sum= a + b;
return sum;
}
int main()
{
int *s = add(1 , 2);
printf("%d\n",*s);
return 0;
}
#include<stdio.h>
#include<stdlib.h>
int *add_v1(int a,int b){
int *sum = malloc(sizeof(int));
if(sum == NULL){
printf("malloc error\n");
exit(1);
}
*sum= a + b;
return sum;
}
void add_v2(int a,int b, int *sum){
*sum = a + b ;
}
int main()
{
int *s1 = NULL;
s1 = add_v1(1 , 2);
printf("%d\n",*s1);
free(s1);
s1=NULL;
//因为s1在add_v1函数内malloc分配了堆内存,所以使用结束也要free,否者会造成内存泄漏。
//这种函数写法和调用方式很容易造成内存泄漏
int *s2 = (int *)malloc(sizeof(int));
if(s2 == NULL){
printf("malloc error\n");
exit(1);
}
add_v2(1,2,s2);
printf("%d\n",*s2);
free(s2);
s2 = NULL;
return 0;
}
3、常见的内存错误
1、内存没有分配成功,却使用了它。
解决办法:在使用指针前一定要确保指针是有效的。对于使用malloc申请的指针,使用if(p ==NULL)检验指针有效性。
2、内存虽然分配成功,但是并未初始化就使用它。
3、内存越界
4、忘记释放内存,造成内存泄漏
1)动态内存申请没有释放
2)多进程情况下,进程结束没有进行资源回收
3)网络通信中,创建了socket套接字但没有释放
4)打开的文件描述符没有释放
内存泄露简单的讲就是申请了一块内存空间,使用完毕后却没有释放掉。一般表现方式是随着程序运行时间越长,占用内存越多,最后虚拟内存空间用尽,程序奔溃。
5、释放了内存却继续使用它。