基于C语言中野指针的深入解析
“野指针”的成因主要有两种:
(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的地址是:%p\n", p);
strcpy(p, "Hello");
printf("%s\n", p);
free(p);
printf("指针p的地址是:%p\n", p);
system("PAUSE");
return 0;
}
运行截图如下:
可以看出,虽然使用 free(p) ,释放了p指向的地址空间,但是这个指针还是存在的,只是指向的是“垃圾”内存。
此时p的状态就被称为是“野指针”
相关推荐
-
C语言之free函数以及野指针介绍
[FROM MSDN && 百科]原型:void free(void *ptr);#include<stdlib.h>或#include <malloc.h>Deallocate space in memory释放ptr指向的存储空间.被释放的空间通常被送入可用存储区池,以后可在调用malloc.realloc以及realloc函数来再分配.注意:连续两次使用free函数,肯定会发生错误.malloc的次数要和free的次数相等.A block of memory
-
关于c语言指针的两处小tip分享
1:常量指针与指针常量 常量指针与指针常量名字很接近,但是两者区别很大. 常量指针是指指向常量的指针,例如:char const *st[4]="str";或者使用下面的方法,效果是一样的:const char *st[4]="str"; 它声明了一个指针变量,这个指针指向了一个常量字符串,但是由于指向的内存空间是常量,因此该地址的内容是不能修改的,例如:*st="no"; //这是不行的,因为内存空间的内容不能修改st="ok&quo
-
讲解C语言编程中指针赋值的入门实例
从const int i 说起 你知道我们声明一个变量时象这样int i :这个i是可能在它处重新变赋值的.如下: int i = 0; /* . . . */ i = 20; /*这里重新赋值了*/ 不过有一天我的程序可能需要这样一个变量(暂且称它变量),在声明时就赋一个初始值.之后我的程序在其它任何处都不会再去重新对它赋值.那我又应该怎么办呢?用const . /* . . . */ const int ic =20; /* . . . */ ic = 40; /*这样是不可以的,编译时是无
-
c语言:基于函数指针的两个示例分析
第一个:------------------------------------------------------ 复制代码 代码如下: #include <stdio.h>#include <string.h>void tell_me(int f(const char *, const char *));int main(void){ tell_me(strcmp); tell_me(main); return 0;}void tell_me(int f(const
-
Swift与C语言指针结合使用实例
Objective-C和C的API常常会需要用到指针.Swift中的数据类型都原生支持基于指针的Cocoa API,不仅如此,Swift会自动处理部分最常用的将指针作为参数传递的情况.这篇文章中,我们将着眼于在Swift中让C语言指针与变量.数组和字符串共同工作. ####用以输入/输出的参数指针 C和Objective-C并不支持多返回值,所以Cocoa API中常常将指针作为一种在方法间传递额外数据的方式.Swift允许指针被当作inout参数使用,所以你可以用符号&将对一个变量的引用作为指
-
简单分析C语言中指针数组与数组指针的区别
首先来分别看一下,指针数组的一个小例子: #include <stdio.h> #include <string.h> int lookup_keyword(const char*key, const char* table[], const int size) { int ret = -1; int i = 0; for(i=0; i<size; i++) { if (strcmp(key, table[i]) == 0) { ret = i; break; } } ret
-
举例理解C语言二维数组的指针指向问题
之前对数组的概念一直没有理解透彻,只觉得数组名就是个常量指针而已,用法和基本的指针差不多.所以当我尝试用二级指针去访问二维数组时,就经常会出错.下面就是刚开始写的一个错误的程序: #include <stdio.h> int main() { int iArray[2][3] = {{1,2,3},{4,5,6}}; int **pArray = NULL; pArray = iArray; printf("array[0][0] = %d\n", pArray[0][0]
-
C语言指针入门学习面面观
这似乎是一个很凝重的话题,但是它真的很有趣. 1. 指针是指向某一类型的东西,任何一个整体,只要能称为整体就能拥有它自己的独一无二的指针类型,所以指针的类型其实是近似无穷无尽的 2. 函数名在表达式中总是以函数指针的身份呈现,除了取地址运算符以及sizeof 3. C语言最晦涩难明的就是它复杂的声明: void (*signal(int sig, void (*func)(int)))(int),试试着把它改写成容易理解的形式 4. 对于指针,尽最大的限度使用const保护它,无论是传递给函数,
-
C语言中下标与指针的转换以及指向指针的指针的例子
下标到指针之间和转换 以下的程序做了什么. #include <stdio.h> int main() { int a[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}; int i = 0; int j = 0; for(i = 0; i<3; i++) { for(j=0; j<3; j++) { printf("%d\n", *(*(a+i)+j)); } } } 打印了数组中的每个元素: 指向指针的指针 #include
-
基于C语言中野指针的深入解析
"野指针"的成因主要有两种:(1)指针变量没有被初始化.任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气.所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存.例如 复制代码 代码如下: char *p = NULL; char *str = (char *) malloc(100); (2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针.参见7.5节.别看free和dele
-
C语言中的指针以及二级指针代码详解
很多初学者都对C中的指针很迷糊,希望这篇blog能帮助到大家: 1.什么是"指针": 在执行C程序的时候,由于我们的数据是存储在内存中的.所以对于C程序本身来说,如果想找到相应被调用的数据,就要知道存储该数据的内存地址是多少,换言之,C程序通过已知的内存地址到相应的内存位置存储数据. 这里简单说一下内存管理(对于初学者来说.为了避免专业术语引发的理解问题,下面的叙述尽量避免专业定义:),对于现代计算机系统来说,内存空间分为两个区域,一个是"数据区",一个是"
-
详解C语言中的指针与数组的定义与使用
指针的特点 他就是内存中的一个地址 指针本身运算 指针所指向的内容是可以操作的 操作系统是如何管理内存的 栈空间 4M~8m的大小 当进入函数的时候会进行压栈数据 堆空间 4g的大小 1g是操作系统 全局变量 内存映射 可以对内存的内容修改修改硬盘的内容 一般在数据库中经常使用 内存的分配与释放 c语言分配内存的方法 // malloc(需要分配的大小): 这里的分配的大小需要对齐的2的指数 void *mem = malloc(size); 释放内存 // 一般分配的内容都是在堆空间中的 //
-
C语言中的指针 初阶
目录 1.指针是什么 2.指针和指针类型 3.野指针 3.1野指针成因 3.2如何规避野指针 4.指针的运算 4.1指针±整数 4.2指针-指针 4.3指针的关系运算 5.指针和数组 6.二级指针 7.指针数组 1.指针是什么 初学者都有一个疑问,那就是指针是什么?简单的说,就是通过它能找到以它为地址的内存单元. 地址指向了一个确定的内存空间,所以地址形象的被称为指针. int main() { int a = 10; int* pa = &a; return 0; } //pa是用来存放地址(
-
一文带你了解Go语言中的指针和结构体
目录 前言 指针 指针的定义 获取和修改指针所指向变量的值 结构体 结构体定义 结构体的创建方式 小结 前言 前面的两篇文章对 Go 语言的基础语法和基本数据类型以及几个复合数据类型进行介绍,本文将对 Go 里面的指针和结构体进行介绍,也为后续文章做铺垫. 指针 在 Go 语言中,指针可以简单理解是一个地址,指针类型是依托于某一个类型而存在的,例如 Go 里面的基本数据类型 int.float64.string 等,它们所对应的指针类型为 *int.*float64.*string等. 指针的定
-
Go语言中的指针运算实例分析
本文实例分析了Go语言中的指针运算方法.分享给大家供大家参考.具体分析如下: Go语言的语法上是不支持指针运算的,所有指针都在可控的一个范围内使用,没有C语言的*void然后随意转换指针类型这样的东西.最近在思考Go如何操作共享内存,共享内存就需要把指针转成不同类型或者对指针进行运算再获取数据. 这里对Go语言内置的unsafe模块做了一个实验,发现通过unsafe模块,Go语言一样可以做指针运算,只是比C的方式繁琐一些,但是理解上是一样的. 下面是实验代码: 复制代码 代码如下: packag
-
C语言中函数指针的三种使用方法总结
C语言中函数指针的三种使用方法总结 在这里分享一下自己的心得,希望和大家一起分享技术,如果有什么不足,还请大家指正.写出这篇目的,就是希望大家一起成长,我也相信技术之间没有高低,只有互补,只有分享,才能使彼此更加成长. 定义方式:int (*p)(int x, int y); 实现代码: #include <stdio.h> int sum(int x, int y){ return x + y; } int reduce(int x, int y){ return x - y; } int
-
C语言中二级指针的实例详解
C语言中二级指针的实例详解 用图说明 示例代码: #include <stdio.h> int main(int argc, const char * argv[]) { // int a = 5; int *p1 = &a; //-打印地址-----地址相同--------------- printf("&a = %p\n", &a);// printf("p1 = %p\n", p1);// int **p2 = &p
-
详解C语言中二级指针与链表的应用
目录 前言 二级指针讲解 链表的应用 定义双链表的结构体 创建双链表 前言 这篇文章即将解决你看不懂或者不会写链表的基本操作的问题,对于初学者而言,有很多地方肯定是费解的.比如函数的参数列表的多样化,动态分配内存空间函数malloc等,其实这些知识和指针联系紧密,尤其是二级指针.那么开始好好的学习这篇文章吧! 二级指针讲解 简述:其实就是一个指针指向另一个指针的地址. 我们都知道指针指向地址,但是指针自身也是一个变量,当然也可以被二级指针所指向. 语法:形如 int x = 10; int *q
-
C语言常见的指针笔试题解析
目录 笔试题1 笔试题2 笔试题3 笔试题4 笔试题5 笔试题6 笔试题7 笔试题8 在我们学习指针之后,应该在实际应用中去理解和掌握它,毕竟实践才是检验真理的唯一标准,我们以后在找工作的过程中免不了会遇到与指针相关的试题,本篇文章可以帮助我们提前了解一些常见的指针考点.在学习这篇文章之前可以根据需要对指针进行简要复习. 注:本篇文章所有代码均在X86环境下运行. 笔试题1 #include <stdio.h> int main() { int a[5] = { 1,2,3,4,5 }; in
随机推荐
- java调用百度定位api服务获取地理位置示例
- firefox下jquery ajax返回object XMLDocument处理方法
- jQuery在页面加载时动态修改图片尺寸的方法
- java 流操作对文件的分割和合并的实例详解
- 浅析PHP中call user func()函数及如何使用call user func调用自定义函数
- Zend Framework教程之视图组件Zend_View用法详解
- javascript实现的一个带下拉框功能的文本框
- python实现文本去重且不打乱原本顺序
- 用sql脚本创建sqlserver数据库范例语句
- Anroid四大组件service之本地服务的示例代码
- Win2008 R2安装.NET Framework 4的windows6.1-KB958488-V6001-x64出现灾难性故障解决方法
- Lua中的迭代器和泛型for实例
- jQuery使用$.each遍历json数组的简单实现方法
- java 中序列化NotSerializableException问题解决办法
- Java实现MD5消息摘要算法
- IOS实现百度地图自定义大头针和气泡样式
- javascript学习随笔(使用window和frame)的技巧
- PHP面向对象五大原则之开放-封闭原则(OCP)详解
- Python堆排序原理与实现方法详解
- 两个List集合取相同重复数据的方法