野指针成因详解

之前写程序的时候报出段错误:segmentation fault就写了一边关于段错误的介绍。详细介绍在http://t.csdnimg.cn/6y56l。但是说到底段错误不过是野指针的成因之一。这篇主要讲解野指针的产生和解决方法。

野指针概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
可能对于这句话很多人不是很理解。那么理解下面一句话;我们创建变量存储数据的过程,本质上就是向内存申请空间。而内存单元有自己的编号就像我们每个小区的单元号,我们把这个给编号叫做地址。我们根据这个编号找到地址的过程就是指针。
那么理解一下  地址等于指针;指针指向的位置是不可知的,说明什么?我们申请的内存空间是随机不确定的。
我总结了野指针的主要成因有以下几点:
1.指针未初始化;
2.指针越界访问;
3.指针指向的地址被释放;
第一种: 1.指针未初始化;
下面看一行代码:
int main()
{
	int* p;
	*p = 10;
	return 0;
}

int* p局部变量指针未初始化,默认为随机值;这个变量不初始化,代表随机值,我们不知道它里面是什么?有没有被使用?能不能用?我们把这种使用内存单元的情况叫不合法使用内存。

而当我们*p = 10;这样去使用一个不合法的内存,就会造成野指针;

解决方法也很简单:对指针进行初始化;具体方法有下面几种:

int main()
{
	int a = 10;
	int b = 4;
	int* p = &a;//直接初始化;
	*p = 3;
	int* q = NULL;//当我们不确定给这个给指针赋什么值就可以给他赋值NULL
	//表示为空,当我们需要时重新初始化;
	int* q = &b;
	return 0;
}

第二种:2.越界访问

同样我们看一个代码:

int main()
{
	int arr[10] = { 0 };
	int* p = arr;
	int i = 0;
	for (i = 0; i <= 10; i++)
	{
		*p = i;
		p++;
	}
	return 0;
}

我们定义一个数组,然后通过指针来把数组里面的元素改变为1,2,3.......9.但是实际上数组只有10元素。从0开始到9,当指针指向的范围超出数组arr的范围时,p就是野指针也就是超出边界。这就要我们注意内存单元的边界;

0123456789    未知  

int main()
{
	int arr[10] = { 0 };
	int* p = arr;
	int i = 0;
	for (i = 0; i <10; i++)
	{
		*(p++) = i;
		printf("%d ", arr[i]);
	}
	
	return 0;
}

看以下效果:

第三种:指针指向的地址被释放;

这种往往在我们构建函数的过程当中会出现这中问题;简单举个栗子:

int* test()
{
	int a = 10;
	int* q = &a;
	return q;
}
int main()
{
	int* p = test();
	return 0;
}

我们简单创建一个函数返回这个函数里面变量a的地址q给p看似是不是没有问题?

但是这个函数里面的a时局部变量,当函数进行到这的时候,a被创建,当执行完以后就会被销毁(释放)从而不存在或者说,a的地址不在属于a。我们的指针p接收的就会时一个随机值,不确定的地址,从而导致野指针的产生。

所以要求我们在使用指针的时候要检测指针的合法性!

当然我们也可以结合static和const的使用,延长生命周期或者演变为常量,或者使用全局变量来改变这种情况。

简单写一下:

int* test()
{
	const int a = 10;
	int* q = &a;
	return q;
}
int main()
{
	int* p = test();
	printf("%d", *p);
	return 0;
}

这样就可以运行

下面是对于使用指针的注意地方的总结:

1.指针初始化;

2.小心指针越界;

3.指针指向空间是否被释放;

4.避免使用返回局部变量的地址;

5.指针使用前检查有效性

总的来说野指针的问题还是集中一句话,内存不合法使用所导致产生。

需要代码的可以到我gitee上找:链接:https://gitee.com/luochen-su-yu/causes-and-solutions.git

  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值