野指针问题

  关于这一点本来是不想写的,一直觉的是些旁枝末叶的东西,很容易就能掌握,或者说不会犯错的地方,但这两天敲代码的时候就遇到了这样的问题,或者说不容易犯错的地方才最容易犯错吧!下面切入正题:

  何为野指针,对一个指向空地址的指针我们将其称为野指针,即所指向的地址不能进行操作的指针;(这两天写C++的时候就遇到了这个问题,我把指针重新指向了未分配的空间并对其进行了操作!刚开始硬是不知道自己错在哪!来来回回的看来好几遍才想到这一点);

  下面先来看一段代码;

  

 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <stdlib.h>
 5 
 6 void distribution(char **str)//分配空间
 7 {
 8     char *tmp = NULL;//辅助指针变量
 9 
10     if(str == NULL)//如果传递过来的地址为空,则不执行以下操作
11     {
12         printf("error\n");
13         return ;
14     }
15 
16     tmp = (char *)malloc(sizeof(char)* 5);
17     if(tmp == NULL)
18     {
19         printf("error");
20         return;
21     }
22     strcpy(tmp,"aaa");//将aaa字符串copy到分配的内存空间中
23     *str = tmp;//可以通过二级指针来操作一级指针的指向//即间接赋值是指针存在的最大意义
24     
25     /********************************/
26     //然后我们将透tmp所指向的内存空间释放掉
27     free(tmp);
28     /********************************/
29 }
30 
31 void main()
32 {
33     char *point;
34     distribution(NULL);//如果我们传递一个空地址过去,而且没有合理的处理,编译器会直接报错
35 
36     distribution(&point);//因为是同二级指针所以我们要将一级指针的地址传递过去
37     if(point != NULL)//如果point不是指向NULL我们就打印字符串
38     {
39         printf("%s\n",point);//结果打印出来的是一堆乱码
40         
41     }
42 
43     if(point != NULL)
44     {
45         free(point);//当编译器执行到这一步的时候会停止调试
46     }
47 
48 
49     system("pause");
50     return;
51 }

    在这里我们可以看到,在distribution()函数中虽然我们已经在栈区分配了内存,并将指针指向了它,但是当我们将其释放掉之后,并不能判断出它已经是空指针了,而且会打印出一堆乱码,并且再次对这块内存进行释放的时候 free(point) 我们会发现编译器会直接报错(老版本的编译器搞不好会直接当机);

  那么问题就出来了,明明已经将内存释放掉了,为什么,编译器认为它指向一个空间:即if(point != NULL)并不能判断出它所指向的地址已经是空地址了:

  所谓的地址就是内存编号,而这个内存编号也就是我们所说的物理地址,我们所能析构的和操作的内存空间,也就是我们对其进行了类型(int ,char等)声明的内存空间,不然是无法对其访问的,所以也就是说释放的内存空间就是将我们所声明的地址类型给抹除了,它就变为了没有类型,没有类型不是void类型,但是物理地址是无法被释放的,不然我们要到哪里去操作内存空间呢?所以即使释放掉了内存空间,地址仍然存在,所以身为一个负责任的人我们应该在释放完内存之后,将其指向NULL(这也是为什么很多资料上在要求定义变量的时候就初始化的原因吧!);

  **str = &point;// * 就像一把钥匙,通过*str可以达到改变point指向的效果,**str可以达到改变*point(改变具体值)的效果;

  free(tmp); tmp = NULL;通过free(tmp),直接释放掉了在在堆区所分配的内存,但是指向这个内存块的的地址符是不会改变的,即在tmp在没有指向NULL的时候*str所指向的地址符和tmp时一样的,所以释放的tmp所指向的内存块,即释放了*str所指向的内存块,但是*str的内存快并没有改变,所以此时应该在加上*str = NULL,这样point也会指向null,而不会指向一个只有地址符的内存块(即野指针);

  在进行内存分配的时候我们也要知道我们是不是用NULL指向了一个地址,即

  distribution(NULL);//如果我们传递一个空地址过去,而且没有合理的处理,编译器会直接报错
  如果不对其判断直接执行

//if(str == NULL)//如果传递过来的地址为空,则不执行以下操作
  *str = tmp;//可以通过二级指针来操作一级指针的指向//即间接赋值是指针存在的最大意义
  编译器会直接报错,因为无法使用NULL指向一个地址;
  
posted @ 2017-11-09 23:51  SmartGame  阅读(2123)  评论(1编辑  收藏  举报