指针,C语言开发者表示很淦,指针的使用,很多人表示不敢直面ta,不像Java一样,有垃圾自动回收功能,我们不用担心那么多内存泄漏等问题,那C语言里边呢,指针又分为了"野指针","迷途指针" 。 你是不是更迷糊了,这篇一起来攻克ta!

  • 发现我的封面似乎致敬了一下路痴"索隆",刚好跟我们今天的主角一样,找不着北的"迷途"指针hhh

悬垂指针/迷途指针定义

  • 当所指向的对象被释放或者收回,但是对该指针没有作任何的修改,以至于该指针仍旧指向已经回收的内存地址,此情况下该指针便称悬垂指针(也叫迷途指针)。

野指针定义

  • 野指针指的是还没有初始化的指针(导致我们不知道他会指向哪里)
	int* p;
//没有初始化就使用他
printf("%p", p);

编译器一般会提示你出错了!

常见错误:

1。指针定义时未被初始化:

  • 指针在被定义的时候,如果程序不对其进行初始化的话,它会随机指向一个区域

这种指针就是我们上边所说的野指针

//先定义一个指针(没有初始化)
int *p ;
//然后就使用这个指针
*p =12;

2。指针释放后没有置空:

  • 我们在用malloc()开辟空间的时候,要检查返回值是否为空

    • 如果为空,则开辟失败;
    • 如果不为空,则指针指向的是开辟的内存空间的首地址。
  • 指针指向的内存空间在用free()或delete释放后,此时指针指向的就是“垃圾”内存。如果我们没有对其进行置空或者其他赋值操作的话,就有可能会成为悬垂指针/迷途指针 。

free

free() 只能释放动态分配的内存空间,并不能释放任意的内存。下面的写法是错误的

int a[10];
free(a);

注意:free() 不会改变 np 变量(一个指向结构体的指针)本身的值,调用 free() 后它仍然会指向相同的内存空间

可以把他理解为,原本np指向了一个房子,现在free了,把房子里的人赶了出去,而np仍然指向这个房子

但是此时该内存已无效,不能被使用。

把他们打印出来的话还是一样的,但是再访问的话



free之后访问到的数据就奇奇怪怪的了

规避方法

建议在 free操作后 将 np 的值设置为 NULL,例如:

free(np);
np=NULL;

3。在方法中定义变量,返回该变量的地址

  • 先来看一个实例
#include"stdio.h"
int* tempAddress() {
int temp1[] = { 1,2,3 };
return temp1;
}
int* tempAddress2() {
int temp2[] = { 4,5,6 };
return temp2;
}
int main() {
//第一次
int* temp = tempAddress();
printf("%d\n", *temp);
//调用另一个完全不一样的函数
tempAddress2();
//重新输出
printf("%d\n", *temp);
}



诶?明明第一次还能输出出来来着,怎么后边调用了另一个完全不一样的函数之后就输出变得那么奇怪了呢?

  • 要知道,我们每个方法执行的时候,都会为这个方法去分配一个栈帧,当这个函数返回时,为栈帧分配的那一块内存区域可能就已经被释放了,但是数据还未清理
  • 但是任何接下来的函数调用都可能又会把刚才释放掉的那块空间给占用了。导致再输出temp所指向的值时,就变成我们新修改的值了

可能看到这里有的同学会有疑问了?诶,那free跟这个方法栈的回收有什么区别呢?为什么free过后是直接不能访问呢,而方法栈的回收却只是把区域回收了,但是数据还没有清理掉

其实我们free,通常都是搭配malloc来使用的,何谓malloc,malloc是我们程序员手动在中开辟一个空间,可以自己进行管理,不会像栈一样,出了函数就自动被回收了

来看我们用malloc能不能解决上边那个问题

int* tempAddress() {
//int a[] = { 1,2,3 };
int* a = (int*)malloc(sizeof(int) * 3);
a[0] = 1;
return a;
}
int* tempAddress2() {
//int b[] = { 4,5,6 };
int* b = (int*)malloc(sizeof(int) * 3);
b[0] = 4;
return b;
}
int main() {
int* temp = tempAddress();
printf("%d\n", *temp);
tempAddress2();
printf("%d\n", *temp);

  • 是不是美滋滋,我们可以自己手动控制这块区域了,要回收也是我们自己回收,不会说出了函数体就被自动回收了

堆栈需要注意的问题

内存空间不足,内存泄漏

malloc一时爽,一直malloc一直爽,随着我们开发不断的malloc,可能会带来什么问题呢?

  • 最显而易见的当然是我们的内存空间分配的问题,当我们malloc的数量,空间内存越来越大时,势必会造成堆内存的无限膨胀,。长期运行将会导致可用内存越来越少,程序也将会变得越来越卡顿。如果我们不手动释放,那就要到程序结束才会释放。可能会出现内存泄露(就是我们前边所提及到的)等问题

堆栈溢出/缓冲区溢出

使用过多的存储器时导致调用堆栈产生的溢出,也是缓冲区溢出中的一种

  • 一般在递归中产生。堆栈溢出很可能由无限递归(Infinite recursion)产生,但也可能仅仅是过多的堆栈层级。

最常见的情况就是无限递归了

int fun()
{
//这里递归没有一个终止条件,会无限调用
return fun();
}

写在最后

  • 关于递归,在之后的数据结构专栏我们还会涉及到(归并排序和快速排序等) , 还有不同语言的垃圾回收机制, 等到melo进一步学习了Java中的垃圾回收后,我们再来聊一聊!

"迷途"的野指针,都快找不着北了的更多相关文章

  1. 使用AFNetworking时, 控制器点击返回销毁了, 但还是会执行请求成功或失败的block, 导致野指针异常

    原本我以为是我程序框架有问题...后来才知道, 无知真可怕... __unsafe_unretained __block typeof(self) weakSelf = self; AFHTTPSes ...

  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. 野指针(Wild pointer)和悬垂指针(dangling pointer)

    详细参考如下: Dangling pointer(悬垂指针.迷途指针)和 Wild pointer(野指针) 迷途指针经常出现在混杂使用malloc() 和 free() 库调用: 当指针指向的内存释 ...

  5. 奇思妙想:利用野指针和lower_bound()/upper_bound()函数实现整数二分

    众所周知,c++的STL中提供了三个二分查找函数,binary_search(),lower_bound(),upper_bound(),功能分别是找某值是否在数组中出现,找到数组中第一个大于等于某值 ...

  6. iOS开发_内存泄漏、内存溢出和野指针之间的区别

    今天,在工作群中,被问到了内存泄漏和野指针指向的区别,自己答的不是很好,特意回来查了资料,在博文中总结一下经验,欢迎指正. 内存泄漏:是指在堆区,alloc 或new 创建了一个对象,但是并没有放到自 ...

  7. NULL指针、零指针、野指针

    1.1.空指针 如果 p 是一个指针变量,则 p = 0; p = 0L; p = '\0'; p = 3 - 3; p = 0 * 17;p=(void*)0; 中的任何一种赋值操作之后, p 都成 ...

  8. 黑马程序员-nil Nil NULL NSNull 野指针和空指针

    空指针1.空指针指不含有任何内存地址的指针.在没有具体初始化之前,其被符值为0Dog * dog = nil;Dog * dog = NULL;都为空指针2.野指针指指向的内存为垃圾内存,导致其值不确 ...

  9. C中的野指针—如何避免

    转自:http://www.cnblogs.com/viviwind/archive/2012/08/14/2638810.html 先看一个例子: struct student{ char* nam ...

随机推荐

  1. 深入HTML5第一天

    页面的title一般是30-40个字符:分别为主页,详情页,列表页  keywords:100个字符  description: em是:emphasize: 强调,着重  i:italic斜体的 : ...

  2. 在Ubuntu18.04安装docker之后,以登陆用户身份执行docker pull jenkins,报错:connect: permission denied

    Using default tag: latest Got permission denied while trying to connect to the Docker daemon socket ...

  3. JMeter脚本开发

    什么是jmeter脚本 用户操作系统的动作流程 用户操作系统的请求 类似演戏的剧本 怎么快速开发漂亮的jmeter脚本 准确 快速 漂亮,脚本逻辑清晰,维护性高 脚本开发方案 代理 http代理服务器 ...

  4. Python项目生成requirements.txt文件之pipreqs的使用

    生成requirements.txt时使用pip freeze > requirements.txt会将环境下所有的安装包都进行生成,再进行安装的时候会全部安装很多没有的包.耗时耗力其实是不可取 ...

  5. GIS应用|快速搭建REST地图服务

    SuperMap Online云存储作为您的"在线GIS云盘",除了可以在云端存储GIS数据,还可以将数据直接发布多种REST服务,为您节省购买和部署SuperMap iServe ...

  6. P4450-双亲数,P5221-Product,P6055-[RC-02]GCD【莫比乌斯反演,杜教筛】

    除了最后一题都比较简单就写一起了 P4450-双亲数 题目链接:https://www.luogu.com.cn/problem/P4450 题目大意 给出\(A,B,d\)求有多少对\((a,b)\ ...

  7. 深入浅出WPF-05.控件与布局

    控件与布局 突出特点:1.专门的UI设计语言XAML,无需像MFC那样使用编程语言设计UI.2.前几代在UI和数据交互方面是由消息Message到控件事件,始终是把UI控件放在主导位置而把数据放在了次 ...

  8. pandas 基础命令

    参考链接:https://github.com/rmpbastos/data_science/blob/master/_0014_Boost_your_Data_Analysis_with_Panda ...

  9. DOC命令和批处理命令

    本文章以极简的方式展现,相信能够浏览到这篇文章的人都对批命令有了一定的了解,我不会把文章写的长篇大论 重要!!! (命令/?)查看帮助文档 (命令/help)查看详细帮助文档 附:思维导图 批处理编程 ...

  10. C++核心编程 4 类和对象-对象的初始化和清理

    构造函数和析构函数 对象的初始化和清理工作是两个非常重要的安全问题,一个对象或者变量没有初始状态,对其使用结果是未知的,同样,使用完一个对象或变量,没有及时清理,也会造成一定的安全问题.C++利用了构 ...