C/C++中的指针让程序员有了更多的灵活性,但它同时也是一把双刃剑,如果用的不好,则会让你的程序出现各种各样的问题,有人说,C/C++程序员有一半的工作量是花在处理由指针引起的bug上,可想而知,指针中包含的陷阱是多么可怕。既然如此,我们在编写代码的时候就应该把好关。

要想在编写代码的时候尽可能避免指针带来的问题,就需要知道不恰当的使用指针到底会引发哪些问题, 又该如何去避免它?下面一起来总结在使用指针时容易遇到的问题。

 

1.避免内存泄露

程序在运行的时候需要内存,同时我们也知道内存是有限的,是计算机特别宝贵的资源,对于使用完的内存,应当及时的归还给操作系统。

在c/c++中,如果是栈上的内存(比如说函数中的局部非静态变量),在使用完之后,操作系统会帮我们自动回收;但是如果是通过动态分配得到的堆上的内存,需要我们手动释放。

如果我们在程序中忘了释放这些动态内存,而程序又是会持续运行的服务进程,会导致内存占用越来越高,轻者致残影响系统性能,重者致命导致进程崩溃。

总之一句话,不再用到的内存没有释放,就叫做内存泄露,内存泄露的问题很严重。好了,让我们看几个内存泄露的案例。

在C/C++中,通过动态内存分配函数或者new运算符分配的动态内存在使用完之后需要手动释放。否则会造成内存泄露。

 

建议:代码编写时注意malloc/free, new/delete成对使用

即使在malloc/new后显示调用了free/delete释放内存,但是由于异常可能会导致释放内存的free/delete语句得不到执行,也会发生内存泄露,下面的例子就是这种情况。

 

从运行结果来看,类的析构函数没有被执行,可推知delete语句并没有得到执行。

有人会说,这还不简单,直接在catch语句的cout << "Something has gone wrong" << endl;下面之后加个delete t不就行了?

没错,这只是个几十行代码的测试程序,你可能一下就看出问题了,但是如果你面对的是一个庞大的工程时候,我想你内心一定是好崩溃的。还有更好的办法来解决这种问题,就是智能指针,后面会有专门的文章介绍。

建议:C++代码代码中多注意使用智能指针

2、不要使用野指针

野指针也叫悬挂指针,是指向“垃圾”内存的指针,使用“野指针”会让程序出现不确定的行为。

注意,野指针不是NULL指针, 它比NULL指针更容易犯错,因为它不能通过形如 if (NULL == p)的判断语句来预防,只能我们自己在写代码时多注意。

指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针,事实上free或delete只是把指针所指的内存给释放掉,但是指针的值还是这块内存的地址,只不过这块内存已经被回收了不能被该进程再使用,下面的例子就是一个典型的使用野指针的案例。

 

建议:free或delete之后将相应的指针设置为NULL

在创建指针变量p时忘了初始化,p的值是个随机的垃圾值,此时读写该指针都是危险的,程序会产生不确定的行为

 

建议:定义指针变量的时候尽量初始化,哪怕初始化为NULL也好

c/c++中,局部变量是存放在栈中的,它的特点是随函数调用时创建随函数结束时销毁,因此在程序中将局部变量的地址返回后赋值给一个指针,这个指针指向的是一个已经被回收的内存,这也是一种野指针。

看看下面的例子,原本是想将fun函数中的变量i的地址返回给p,用p访问这个变量,这个打印出*p是32767,并不是变量i的值8。像这种bug,一旦在大的项目中出现是很难定位的。

建议:不要在函数中返回局部变量的地址,如果代码的逻辑非要是一个局部变量的地址,那么该局部变量一定要申明为static类型,因为static变量的生存期是整个程序运行期间

3、不要使用NULL指针

大家都知道,在程序中不能使用NULL指针,但是如果不注意,程序中还是有可能在你的意料之外就使用到NULL指针,下面看两个比较容易出问题的例子。

动态内存分配函数分配内存的时,有可能会分配失败,此时返回NULL

从程序运行结果来看,malloc分配失败返回NULL赋给p,再通过p访问其所指向的0地址内存内容时,出现"Segmentation fault"错误。

建议:在使用内存分配函数分配内存的时候,应该用i f(p==NULL) 或if(p!=NULL)进行防错处理。

此外,在含有指针参数的函数,也是有可能会误用到NULL指针,当调用该函数时传递的指针是个空指针,如果没有if(p!=NULL) 的判断条件,那么在后面使用指针的时候麻烦就大了,下面的例子就是这种情况。

建议:对于含有指针参数的函数,也应当在函数入口处用if(p==NULL) 或if(p!=NULL)进行防错处理。

看到这里是不是有学习到了很多呢~

如果你很想学会编程,那么小编推荐我的C语言/C++编程学习基地【点击进入】!

 

都是学编程小伙伴们,带你入个门还是简简单单啦,一起学习,一起加油~

还有许多学习资料和视频,相信你会喜欢的!

涉及:游戏开发、常用软件开发、编程基础知识、课程设计、黑客等等......

 

新手学习C/C++编程过程中常见的那些坑,一定要多多注意!的更多相关文章

  1. SQL优化过程中常见Oracle HINT

    在SQL语句优化过程中,我们经常会用到hint,现总结一下在SQL优化过程中常见Oracle HINT的用法: 1. /*+ALL_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳吞吐量, ...

  2. 数据结构笔记01:编程面试过程中常见的10大算法(java)

    以下是在编程面试中排名前10的算法相关的概念,我会通过一些简单的例子来阐述这些概念.由于完全掌握这些概念需要更多的努力,因此这份列表只是作为一个介绍.本文将从Java的角度看问题,包含下面的这些概念: ...

  3. RT3070 USB WIFI 在连接socket编程过程中问题总结

    最近耗时多天,成功的将RT3070驱动.并解决了socket的网络编程,成功的在BA9G10上面实现了USB wif.连上家里的无线路由器,通过ubuntu下面建立的服务端程序,将BA9G10中的数据 ...

  4. [学习笔记] Web设计过程中该做和不该做的

    原文网址: http://www.javascriptstyle.com/the-dos-and-donts-of-web-design -该做的: QR代码QR代码即快速响应代码,这是矩阵条形码的一 ...

  5. Devc++编程过程中的一些报错总结

    以下都是我在使用Devc++的过程中出现过的错误,通过查找资料解决问题,今天小小地记录.整理一下. 1.[Error] invalid conversion from 'const char*' to ...

  6. Loadrunner脚本回放 场景运行过程中常见错误分析

    问题一:Loadrunner超时错误问题描述 Loadrunner超时错误:在录制Web协议脚本回放时超时情况经常出现,产生错误的原因也有很多,解决的方法也不同. 问题现象Error -27728: ...

  7. QT4编程过程中遇到的问题及解决办法

    1.QLineEdit显示内容的格式函数: QLineEdit *lineEditPassword = new QLineEdit: lineEditPassword -> setEchoMod ...

  8. APP store 上架过程中碰到的那些坑&被拒的各种奇葩原因整理&审核指南中文版

    苹果官方发布的十大常见被拒原因 1.崩溃次数和Bug数量.苹果要求开发者在将应用提交给App Store之前彻查自己的应用,以尽量避免Bug的存在. 2.链或错误的链接.应用中所有的链接必须是真实且有 ...

  9. 使用ffmpeg视频编码过程中踩的一个坑

           今天说说使用ffmpeg在写视频编码程序中踩的一个坑,这个坑让我花了好多时间,回头想想,非常多时候一旦思维定势真的挺难突破的.以下是不对的编码结果:                   ...

随机推荐

  1. Echars 参数说明

    theme = { // 全图默认背景 // backgroundColor: 'rgba(0,0,0,0)', // 默认色板 color: ['#ff7f50','#87cefa','#da70d ...

  2. lua数据结构之table的内部实现

    一.table结构 1.Table结构体 首先了解一下table结构的组成结构,table是存放在GCObject里的.结构如下:   typedef struct Table {   CommonH ...

  3. Intersection of Two Prisms(AOJ 1313)

    原题如下: Suppose that P1 is an infinite-height prism whose axis is parallel to the z-axis, and P2 is al ...

  4. [LeetCode] 139. 单词拆分(DP)

    题目 给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词. 说明: 拆分时可以重复使用字典中的单词. 你可以假设字典中没 ...

  5. [LeetCode]55. 跳跃游戏(贪心)

    题目 给定一个非负整数数组,你最初位于数组的第一个位置. 数组中的每个元素代表你在该位置可以跳跃的最大长度. 判断你是否能够到达最后一个位置. 示例 1: 输入: [2,3,1,1,4] 输出: tr ...

  6. Windows下使用Nginx+Tomact做负载均衡

    前言 今天,王子与大家闲谈一下如何在Windows下使用Nginx+Tomcat做负载均衡的完整步骤,小伙伴们可以试着自己动手实践一下哦. 另外说明一点,本篇文章是纯实操文章,不涉及太多原理的解读,后 ...

  7. Docker介绍及常用操作演示(一)

    Docker简介 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互 ...

  8. oracle adf 入门

    入门必踩坑 坑1:jdeveloper里没有mysql的driver,在maven库里引入了,connection里连接正常,但是deploy出错,can't load driver.即使在项目和to ...

  9. python文档翻译之python说明

    3.1使用Python进行计数 让我们来使用一些Python的简单命令,通过终端启动解释器等待出现>>>. 3.1.1数值类型 在终端中输入数学表达式,Python解释器会执行这些表 ...

  10. 如何解决Python下 pip install module 下载慢解决方法?

    对于Python来编程的用户最大的一个痛点就是,下载模块是下载速度特别慢,那么有没有解决方法呢? 换Python的pip下载源 1.首先安装一个模块 pqi,在cmd下 pip install pqi ...