NULL指针、零指针、野指针

时间:2022-09-24 09:00:11

1.1、空指针

如果 p 是一个指针变量,则 p = 0; p = 0L; p = '\0'; p = 3 - 3; p = 0 * 17;p=(void*)0; 中的任何一种赋值操作之后, p 都成为一个空指针,由系统保证空指针不指向任何实际的对象或者函数。反过来说,任何对象或者函数的地址都不可能是空指针。(比如这里的(void*)0就是一个空指针。把它理解为null pointer还是null pointer constant会有微秒的不同,当然也不是紧要了)。其实空指针只是一种编程概念,就如一个容器可能有空和非空两种基本状态。

1.2、NULL指针

NULL 是一个标准规定的宏定义,用来表示空指针常量。因此,除了上面的各种赋值方式之外,还可以用 p = NULL; 来使 p 成为一个空指针。

1.3、零指针

零值指针,是值为0的指针,可以是任何一种指针类型,可以是通用变体类型void*,也可以是char*,int*等等。

1.4、空指针向了内存的什么地方(空指针的内部实现)?

标准并没有对空指针指向内存中的什么地方这一个问题作出规定,也就是说用哪个具体的地址值(0x0 地址还是某一特定地址)表示空指针取决于系统的实现。我们常见的空指针一般指向 0 地址,即空指针的内部用全 0 来表示(zero null pointer,零空指针);也有一些系统用一些特殊的地址值或者特殊的方式表示空指针(nonzero null pointer,非零空指针),具体请参见C FAQ。

在实际编程中不需要了解在我们的系统上空指针到底是一个 zero null pointer 还是 nonzero null pointer,我们只需要了解一个指针是否是空指针就可以了——编译器会自动实现其中的转换,为我们屏蔽其中的实现细节。注意:不要把空指针的内部表示等同于整数 0 的对象表示——如上所述,有时它们是不同的。

1.5、对空指针实现的保护政策

既然我们选择了0作为空的概念,在非法访问空的时候我们需要保护以及报错。因此,编译器和系统提供了很好的政策。

我们程序中的指针其实是WINDOWS内存段偏移后的地址,而不是实际的物理地址,所以不同的程序中的零值指针指向的同一个0地址,其实在内存中都不是物理内存的开端的0,而是分段的内存的开端,这里我们需要简单介绍一下WINDOWS下的内存分配和管理制度:

WINDOWS下,执行文件(PE文件)在被调用后,系统会分配给它一个额定大小的内存段用于映射这个程序的所有内容(就是磁盘上的内容)并且为这个段进行新的偏移计算,也就是说我们的程序中访问的所有NEAR指针都是在我们“自家”的段里面的,当我们要访问FAR指针的时候,我们其实是跳出了“自家的院子”到了他人的地方,我们需要一个段偏移地址来完成新的偏移(人家家里的偏移)所以我们的指针可能是OE02:0045就是告诉系统我们要访问0E02个内存段的0045好偏移,然后WINDOWS会自动给我们找到0E02段的开始偏移,然后为我们计算真实的物理地址。

所以程序A中的零值指针和程序B中的零值指针指向的地方可能是完全不同的。

保护政策:

我们的程序在使用的是系统给定的一个段,程序中的零值指针指向这个段的开端,为了保证NULL概念,系统为我们这个段的开头64K内存做了苛刻的规定,根据虚拟内存访问权限控制,我们程序中(低访问权限)访问要求高访问权限的这64K内存被视作是不容许的,所以会必然引发Access Volitation 错误,而这高权限的64K内存是一块保留内存(即不能被程序动态内存分配器分配,不能被访问,也不能被使用),就是简单的保留,不作任何使用。

我们在直接定义一个指针后并不知道这个指针指向何处(而不是有些程序员认为的如同JAVA等语言会自动零值初始化),所以我们一旦非法地直接访问这些未知地内容时,极其有可能会触碰到程序所不能触碰地内存(这时类似64K限制地保护政策又会起效,就如同你不仅随意闯入了陌生人的家(野指针),而且拿着刀子要问他要钱(访问),警察(WINDOWS内存访问保护政策)当然请你去警察局(报错)谈谈),所以养成良好的指针初始化(赋值为NULL)以及使用FREE(或者时DELETE)之后立即再初始化为空是十分必要的!  

1.6、 为什么通过空指针读写的时候就会出现异常?

NULL指针分配的分区:其范围是从 0x00000000到0x0000FFFF。这段空间是空闲的,对于空闲的空间而言,没有相应的物理存储器与之相对应,所以对这段空间来说,任何读写操作都是会引起异常的。空指针是程序无论在何时都没有物理存储器与之对应的地址。为了保障“无论何时”这个条件,需要人为划分一个空指针的区域,固有上面NULL指针分区。

1.7、是否可以定义自己的 NULL 的实现?

NULL 是标准库中的一个reserved identifier (保留标识符)。所以,如果包含了相应的标准头文件而引入了 NULL 的话,则再在程序中重新定义 NULL 为不同的内容是非法的,其行为是未定义的。也就是说,如果是符合标准的程序,其 NULL 的值只能是 0,不可能是除 0 之外的其它值,比如 1、2、3 等。

1.8、malloc 函数在分配内存失败时返回 0 还是 NULL?

malloc 函数是标准 C 规定的库函数。在标准中明确规定了在其内存分配失败时返回的是一个 “null pointer”(空指针)。对于空指针值,一般的文档(比如 man)中倾向于用 NULL 表示,而没有直接说成 0。但是我们应该清楚:对于指针类型来说,返回 NULL 和 返回 0 是完全等价的,因为 NULL 和 0 都表示 “null pointer”(空指针)。(一般系统中手册中都返回NULL)

2、 野指针

“野指针”不是NULL指针,是指向“垃圾”内存的指针。

2.1、 “野指针”的成因主要有两种:

1)指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。例如:
     char *p = NULL;
     char *str = (char *) malloc(100);

2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。

free和delete只是把指针所指的内存给释放掉,但并没有把指针本身干掉。free以后其地址仍然不变(非NULL),只是该地址对应的内存是垃圾,p成了“野指针”。如果此时不把p设置为NULL,会让人误以为p是个合法的指针。如果程序比较长,我们有时记不住p所指的内存是否已经被释放,在继续使用p之前,通常会用语句if (p != NULL)进行防错处理。很遗憾,此时if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。

char *p = (char *) malloc();
strcpy(p, “hello”);
free(p); // p 所指的内存被释放,但是p所指的地址仍然不变

if(p != NULL) // 没有起到防错作用
{
strcpy(p, “world”); // 出错
}

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

struct A
{
int iA;
char c;
 }; 

void Test(void) 
{
A *p;
{
A a; p = &a; // 注意 a 的生命期 ,只在这个程序块中(花括号里面的两行),而不是整个test函数 }
p->c; // p是“野指针”
}

函数Test在执行语句p-c时,对象a已经消失,而p是指向a的,所以p就成了“野指针”。

NULL指针、零指针、野指针的更多相关文章

  1. NULL指针 Void* 和野指针

    在C和C++的语言中常常有这几个概念: NULL指针.空指针.Void *指针.野指针(Wild Pointer)甚至垂悬指针(Dangling Pointer). 1.NULL指针,一般用于指向一个 ...

  2. 野指针与'关键字'NULL

    野指针与'关键字'NULL 一.NULL是什么? 在C/C++中的标准定义: #ifdef __cplusplus //条件编译,判断是c++还是c环境 #define NULL 0 //c++环境 ...

  3. 关于空指针NULL、野指针、通用指针 (转)

    reference:https://www.cnblogs.com/losesea/archive/2012/11/16/2772590.html 首先说一下什么是指针,只要明白了指针的含义,你就明白 ...

  4. 关于空指针NULL、野指针、通用指针

    http://www.cnblogs.com/losesea/archive/2012/11/16/2772590.html 首先说一下什么是指针,只要明白了指针的含义,你就明白null的含义了.假设 ...

  5. OC中的野指针,空指针,nil,Nil,NULL,NSNULL小结

    周末与一个老朋友吃饭聊天,因为他正在培训班学习iOS开发,就随便聊了几句,发现自己OC基础上的欠缺和一些知识点的混淆.特此整理如下. 1.空指针 没有存储任何内存地址的指针就称为空指针(NULL指针) ...

  6. C语言之free函数及野指针

    [FROM MSDN && 百科] 原型:  void free(void *ptr); #include<stdlib.h>或#include <malloc.h& ...

  7. 野指针及c&plus;&plus;指针使用注意点

    避免野指针的产生 “野指针”的成因主要有: 1)指针变量没有被初始化.任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气.所以,指针变量在创建的同时应当被初始化,要么将指 ...

  8. 浅谈 &OpenCurlyDoubleQuote;空指针、野指针、void&ast;”

            Author: JW. Zhou Date: 2014/7/2 一.空指针(0/NULL) 返回NULL和返回0是完全等价的,因为NULL和0都表示空指针,换句话说:空指针是什么,就是 ...

  9. C&plus;&plus;11标准的智能指针、野指针、内存泄露的理解(日后还会补充,先浅谈自己的理解)

    1.野指针的概念.成因以及避免 首先,来说说什么是野指针,所谓野指针就是一个指向未申请访问受限的内存区域或者已经删除了的对象的指针. 什么意思呢?就是本来一个指针指向一个对象.一块内存,但是由于程序( ...

随机推荐

  1. 【圣诞呈献】高性能 Socket 组件 HP-Socket v3&period;1&period;1 正式发布

    HP-Socket 是一套通用的高性能 Windows Socket 组件包,包含服务端组件(IOCP 模型)和客户端组件(Event Select 模型),广泛适用于 Windows 平台的 TCP ...

  2. ThreadLocal实现方式&amp&semi;使用介绍—无锁化线程封闭

    原文出处: xieyu_zy 虽然现在可以说很多程序员会用ThreadLocal,但是我相信大多数程序员还不知道ThreadLocal,而使用ThreadLocal的程序员大多只是知道其然而不知其所以 ...

  3. C语言动态内存分配

    考虑下面三段代码: 片段1 void GetMemory(char *p) { p = (); } void Test(void) { char *str = NULL; GetMemory(str) ...

  4. 20160907&lowbar;Redis问题

    ZC: 今天发现,redis服务器 启动不了了... 下面是 排查/处理过程. 1.查了一遍配置,看了一下前面的博客文章,貌似 这一套流水操作下来应该没问题... 然而,就是起不了... 1.1.安装 ...

  5. 【转】使用genstring和NSLocalizedString实现App文本的本地化

    原地址:http://www.cnblogs.com/U-tansuo/p/IOS_NSLocalizedString.html iOS提供了简便的方法来实现本地化,其中用的最多的就是NSLocali ...

  6. MYSQL 管理笔记&lpar;一&rpar;

    一.查看MySQL 版本   1.在终端下:mysql -V   2.在mysql中:mysql> status; 3:在help里面查找   mysql --help | grep Distr ...

  7. javascript高级函数

    高级函数 安全的类型检测 js内置的类型检测并非完全可靠,typeof操作符难以判断某个值是否为函数 instanceof在多个frame的情况下,会出现问题. 例如:var isArray = va ...

  8. mysql 保留的关键字

    mysql> select precision from Product; ERROR 1064 (42000): You have an error in your SQL syntax; c ...

  9. STL&lowbar;&lowbar;queue&lowbar;的应用

    转:http://hi.baidu.com/xiaotiandm/item/bda34511cf9e99098fbde41a 调用的时候要有头文件: #include<stdlib.h> ...

  10. Python 遇到的坑

    1. 循环导入 AB 互相引用,或者 中间掺入了更复杂的一些--用局部导入解决