基于C语言中野指针的深入解析

“野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用
 

“野指针”的成因主要有两种:
(1)指针变量没有被初始化。
任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。例如

复制代码 代码如下:

char *p = NULL;
     char *str = (char *) malloc(100);

(2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。参见7.5节。
别看free和delete的名字恶狠狠的(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。

用调试器跟踪示例7-5,发现指针p被free以后其地址仍然不变(非NULL),只是该地址对应的内存是垃圾,p成了“野指针”。如果此时不把p设置为NULL,会让人误以为p是个合法的指针。

如果程序比较长,我们有时记不住p所指的内存是否已经被释放,在继续使用p之前,通常会用语句if (p != NULL)进行防错处理。很遗憾,此时if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。

复制代码 代码如下:

char *p = (char *) malloc(100);
     strcpy(p, “hello”);
     free(p);         // p 所指的内存被释放,但是p所指的地址仍然不变
     …
     if(p != NULL)      // 没有起到防错作用
     {
        strcpy(p, “world”);      // 出错
}

示例7-5 p成为野指针
(3)指针操作超越了变量的作用范围。这种情况让人防不胜防,示例程序如下:

复制代码 代码如下:

 class A
{     
public:
     void Func(void){ cout << “Func of class A” << endl; }
};
     void Test(void)
{
     A *p;
           {
                 A a;
                 p = &a;      // 注意 a 的生命期
}
           p->Func();            // p是“野指针”
}

函数Test在执行语句p->Func()时,对象a已经消失,而p是指向a的,所以p就成了“野指针”。但奇怪的是我运行这个程序时居然没有出错,这可能与编译器有关。
实例程序:

复制代码 代码如下:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
  char *p = NULL;
  p = (char*)malloc(sizeof(char)*100);
  printf("指针p的地址是:%pn", p);
  strcpy(p, "Hello");
  printf("%sn", p);
  free(p);

  printf("指针p的地址是:%pn", p);

  system("PAUSE"); 
  return 0;
}

运行截图如下:

可以看出,虽然使用 free(p) ,释放了p指向的地址空间,但是这个指针还是存在的,只是指向的是“垃圾”内存。
此时p的状态就被称为是“野指针”

时间: 2024-08-08 13:09:03

基于C语言中野指针的深入解析的相关文章

基于C语言中野指针的深入解析_C 语言

"野指针"的成因主要有两种:(1)指针变量没有被初始化.任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气.所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存.例如 复制代码 代码如下: char *p = NULL;     char *str = (char *) malloc(100); (2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针.参见7.5节.别看free和dele

C语言中常量指针与指针常量区别浅析

这篇文章主要介绍了C语言中常量指针与指针常量区别,有需要的朋友可以参考一下 常量指针是指--指向常量的指针,顾名思义,就是指针指向的是常量,即,它不能指向变量,它指向的内容不能被改变,不能通过指针来修改它指向的内容,但是指针自身不是常量,它自身的值可以改变,从而指向另一个常量. 指针常量是指--指针本身是常量.它指向的地址是不可改变的,但地址里的内容可以通过指针改变.它指向的地址将伴其一生,直到生命周期结束.有一点需要注意的是,指针常量在定义时必须同时赋初值. 注:也有人将这两个名称的定义与含义

Go语言中的指针运算实例分析_Golang

本文实例分析了Go语言中的指针运算方法.分享给大家供大家参考.具体分析如下: Go语言的语法上是不支持指针运算的,所有指针都在可控的一个范围内使用,没有C语言的*void然后随意转换指针类型这样的东西.最近在思考Go如何操作共享内存,共享内存就需要把指针转成不同类型或者对指针进行运算再获取数据. 这里对Go语言内置的unsafe模块做了一个实验,发现通过unsafe模块,Go语言一样可以做指针运算,只是比C的方式繁琐一些,但是理解上是一样的. 下面是实验代码: 复制代码 代码如下: packag

c语言-C语言中的指针和数组的初始化

问题描述 C语言中的指针和数组的初始化 char a[]=""abcdef"";char *p =""cdefg"";a[1]='A';p[1]='A'; 这段代码有什么问题?#include int main(){ char amessage[]=""now is the time""; char *pmessage = ""now is the time"

c 指针 分配-C语言中通过指针能不能知道它在内存中的分配方案

问题描述 C语言中通过指针能不能知道它在内存中的分配方案 例如char* pstr; 有几种方式: pstr = "123"; char s[] = "123"; pstr = s; pstr = (char*)malloc(4); pstr[0] = '1'; pstr[1] = '2'; pstr[2] = '3'; pstr[3] = ''; 那么,如何通过pstr判断它是哪种方式的? 解决方案 这两种的结果都是一样的不必纠结,只有数组和指针在分配的时候是不同

c语言-C语言中二级指针修改数组问题。

问题描述 C语言中二级指针修改数组问题. 数组相当于一级指针,我写了一个二级指针被调用.结果它总是宕机,求指导,谢谢. 解决方案 这段程序编译会报错吧:cannot convert parameter 1 from 'char (*)[100]' to 'char **' 可以这样 试试看#include #include #include int getMemBuf(char*& p2){ char* tmp = NULL; tmp = (char*)malloc(100); strcpy(t

非递归二叉树遍历-c语言中函数指针作为参数与函数的嵌套

问题描述 c语言中函数指针作为参数与函数的嵌套 函数指针作为另一函数的参数和函数的嵌套的区别,感觉都是调用,有什么不一样呢?他们都适用在什么情况下!(我是在学非递归遍历二叉树时看到的) Status Visit(TElemType e){ printf("%cn",e); return OK; } Status InOrderTraverse(BiTree T ,Status(*Visit)(TElemType e)){ SqStack S; InitStack(S); Push(S,

c语言中有关指针的问题

问题描述 c语言中有关指针的问题 int *p1[3] int (*p2)[3] int *(*p3)[3] int **p4[3] =============上面的这些应该怎样去理解和分析啊?指针这方面刚入门 很多的不太懂,希望能详细解释上面的指针的情况,万分感谢! 解决方案 呵呵,不要这样片面的的拿几个例子,建议去好好理解下面的几个概念: 1.指针 2.指针数组 3 .数组指针 4.函数指针 5.函数指针数组 6.函数指针数组指针. 这几个概念从前往后依此理解,不然会晕. 解决方案二: 这个

c语言-C语言中这个指针定义是什么意思?

问题描述 C语言中这个指针定义是什么意思? const char *const ch 为什么要2个const?分别是什么意思?顺便求详细说一下这个指针具体是什么意思? 编辑下,完整程序如下: #include #include #include #include int find_char(const int, const char *const, const int); int main(int argc, char argv) { bool translate = false, squeez