如何避免和检查C++中的内存错误

C/C++程序员面临内存管理挑战,如内存泄漏、野指针和越界等问题。使用智能指针如unique_ptr和shared_ptr能帮助管理内存,减少错误。此外,静态代码分析工具如cppcheck和clang-tidy可在编译时检查潜在问题,而Valgrind则在运行时检测内存错误。通过互相审查代码和应用这些工具,可以显著提高代码质量和安全性。
摘要由CSDN通过智能技术生成

内存问题一直是C/C++程序员的心头大患,因为没有GC机制,所以需要我们自己管理内存。在 从“new和malloc的不同”出发看CC++的内存分配 一文中,讲述了几种内存错误的例子,那么避免这些陷阱呢?

1. new/delete 、malloc/free、new[]/delete[] 不匹配,导致的内存污染或者内存泄漏

2. 野指针,delete/free之后,没有置NULL,再次使用

3. delete/free之后,再次释放,double free

3. 申请内存之后,没有判断是否成功,直接使用

4. 内存越界,数组下标越界

5. memset 参数错误,造成 内存踩踏, 污染内存

6. 函数返回指向局部指针变量,离开作用域,变量失效了,再使用就可能发生异常。注意,编译时会有警告。空悬指针

7. 内存分配成功,没有初始化

8. 类成员中含有类对象,但使用memset等函数进行内存操作

9. map erase 删除操作会使当前指向被删除元素的迭代器失效。要注意这样删除map.erase(it_pos++);, 这样map.erase(it_pos);再继续访文迭代器是错误的。

10. 缓冲区溢出

 

1. 使用智能指针unique_ptr

unique_ptr是独享被管理对象指针所有权的智能指针,离开作用域之后会自动销毁对象释放资源,可以解决原始指针易别重复释放或者不释放(即内存泄漏)的问题。

 

2. 使用智能指针shared_ptr/weak_ptr

shared_ptr可以解决空悬指针和野指针的问题。shared_ptr中最关键的是增加了一个引用计数,用来标识多少个智能指针访问此资源,这样相比unique_ptr它就可以复制拷贝。并且作为一个原子变量,它本身是线程安全的。但是一定要注意,它所管理的对象不是线程安全的。

 

3. 使用静态代码分析工具

如cppcheck,clang-tidy等

以cppcheck为例子,它可以辅助检查代码,如下问题

1. 自动变量检查

2. 数组的边界检查

3. class类检查

4. 过期的函数,废弃函数调用检查

5. 异常内存使用,释放检查

6. 内存泄漏检查,主要是通过内存引用指针

7. 操作系统资源释放检查,中断,文件描述符

8. 异常STL 函数使用检查

9. 代码格式错误,以及性能因素检查

还有一些具体的未定义行为

  • 死指针
  • 被零除
  • 整数溢出
  • 无效的移位操作数
  • 无效的转换
  • STL的用法无效
  • 内存管理
  • 空指针取消引用
  • 越界检查
  • 未初始化的变量
  • 写入const数据

 

4. Valgrind检查运行时内存错误

最常用的命令格式(test为我们的应用程序):

valgrind --tool=memcheck --leak-check=full ./test

对与malloc()/free()/new/delete的调用都会被捕获。下列问题,它都能动态的检测出来

  • 使用未初始化内存
  • 读/写释放后的内存块
  • 读/写超出malloc分配的内存块
  • 读/写不适当的栈中内存块
  • 内存泄漏,指向一块内存的指针永远丢失
  • 不正确的malloc/free或new/delete匹配
  • memcpy()相关函数中的dst和src指针重叠

基本原理如下图所示

 

Memcheck 会建立了两张全局表

Valid-Value 表:这张表存放了进程地址空间的所有有效数据和CPU寄存器。

Valid-Address 表:1个bit位映射进程地址空间中的一个字节(byte),负责记录该地址是否能够被读写。

Memcheck中内置一个虚拟CPU( 英文为 synthetic CPU、直译为合成CPU),结合上述两张表进行工作。

当内存中的某个字节被加载到CPU中的时候,也会被加载到虚拟CPU中。如果寄存器中的值,对内存产生变化,那么memcheck将会检查Vaild-Value Map, 如果找不到就是尚未初始化,则报告未初始化内存错误。如果读写内存中的某个字节,则会检查Vaild-Address Map,如果这个位置标记的是无效位置,则报告读写错误。valgrind 功能很强大,也不只memcheck一个工具,如果对这块感兴趣,强烈建议直接参考官网的手册 这里

 

5. 相互review

同事之间相互review code,可以提高代码质量。

 

参考

[1] http://cs.swan.ac.uk/~csoliver/ok-sat-library/internet_html/doc/doc/Valgrind/3.8.1/html/mc-manual.html

[2] http://sourceforge.net/p/cppcheck/wiki/

[3] https://en.cppreference.com/w/cpp/memory/shared_ptr

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值