C/C++ 中的指针让程序员有了更多的灵活性, 但它同时也是一把双刃剑, 如果用的不好, 则会让你的程序出现各种各样的问题, 有人说, C/C++ 程序员有一半的工作量是花在处理由指针引起的 bug 上, 可想而知, 指针中包含的陷阱是多么可怕既然如此, 我们在编写代码的时候就应该把好关
要想在编写代码的时候尽可能避免指针带来的问题, 就需要知道不恰当的使用指针到底会引发哪些问题, 又该如何去避免它? 下面一起来总结在使用指针时容易遇到的问题
小编推荐一个学 C 语言 / C++ 的学习裙 六九九, 四七零, 五九六 , 无论你是大牛还是小白, 是想转行还是想入行都可以来了解一起进步一起学习! 裙内有开发工具, 很多干货和技术资料分享!
1. 避免内存泄露
程序在运行的时候需要内存, 同时我们也知道内存是有限的, 是计算机特别宝贵的资源, 对于使用完的内存, 应当及时的归还给操作系统
在 c/c++ 中, 如果是栈上的内存(比如说函数中的局部非静态变量), 在使用完之后, 操作系统会帮我们自动回收; 但是如果是通过动态分配得到的堆上的内存, 需要我们手动释放
如果我们在程序中忘了释放这些动态内存, 而程序又是会持续运行的服务进程, 会导致内存占用越来越高, 轻者致残影响系统性能, 重者致命导致进程崩溃
总之一句话, 不再用到的内存没有释放, 就叫做内存泄露, 内存泄露的问题很严重好了, 让我们看几个内存泄露的案例
在 C/C++ 中, 通过动态内存分配函数或者 new 运算符分配的动态内存在使用完之后需要手动释放否则会造成内存泄露
建议: 代码编写时注意 malloc/free, new/delete 成对使用
即使在 malloc/new 后显示调用了 free/delete 释放内存, 但是由于异常可能会导致释放内存的 free/delete 语句得不到执行, 也会发生内存泄露, 下面的例子就是这种情况
小编推荐一个学 C 语言 / C++ 的学习裙 六九九, 四七零, 五九六 , 无论你是大牛还是小白, 是想转行还是想入行都可以来了解一起进步一起学习! 裙内有开发工具, 很多干货和技术资料分享!
从运行结果来看, 类的析构函数没有被执行, 可推知 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 的值是个随机的垃圾值, 此时读写该指针都是危险的, 程序会产生不确定的行为
小编推荐一个学 C 语言 / C++ 的学习裙 六九九, 四七零, 五九六 , 无论你是大牛还是小白, 是想转行还是想入行都可以来了解一起进步一起学习! 裙内有开发工具, 很多干货和技术资料分享!
建议: 定义指针变量的时候尽量初始化, 哪怕初始化为 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)进行防错处理
来源: http://www.jianshu.com/p/98392e217b1b