zixie1991 / cplusplus-exercise

C++编程练习。。。
8 stars 1 forks source link

valgrind检测内存泄露 #13

Open zixie1991 opened 7 years ago

zixie1991 commented 7 years ago

valgrind检测内存泄露

memcheck探测程序中内存管理存在的问题。它检查所有对内存的读/写操作,并截取所有的malloc/new/free/delete调用。因此memcheck工具能够探测到以下问题:

  1. 使用未初始化的内存
  2. 读/写已经被释放的内存
  3. 读/写内存越界
  4. 读/写不恰当的内存栈空间
  5. 内存泄漏
  6. 使用malloc/new/new[]和free/delete/delete[]不匹配。
  7. src和dst的重叠

    valgrind示例

    使用未初始化的内存

    内存读写越界

    src和dst内存覆盖

memcpy

动态内存管理错误

常见的内存分配方式分三种:静态存储,栈上分配,堆上分配。全局变量属于静态存储,它们是在编译时就被分配了存储空间,函数内的局部变量属于栈上分配,而最灵活的内存使用方式当属堆上分配,也叫做内存动态分配了。常用的内存动态分配函数包括:malloc, alloc, realloc, new等,动态释放函数包括free, delete

一旦成功申请了动态内存,我们就需要自己对其进行内存管理,而这又是最容易犯错误的。常见的内存动态管理错误包括:

申请和释放不一致 申请和释放不匹配 释放后仍然读写

内存泄漏

非法写/读

无效指针

重复释放

释放空指针不算重复释放

char *ptr = NULL;
free(ptr);

valgrind的局限性

valgrind不对静态数组(分配在栈上)进行边界检查。如果在程序中声明了一个数组:

int main() {
    char s[10];
    s[10] = 'a';
    return 0;
}

valgrind则不会警告你,你可以把数组改为动态在堆上分配的数组,这样就可能进行边界检查了。这个方法好像有点得不偿失的感觉。

另:可以使用静态代码检测工具进行检测,如cppcheck

小结

valgrind占用更多的内存——两倍于程序的正常使用量,如果你用valgrind来检测使用大量内存的程序就会遇到问题,它可能会用很长的时间来运行测试。valgrind不可能检测出你在程序中犯下的所有错误——如果你不检查缓冲区溢出(buffer overflow detected),Valgrind也不会告诉你代码写了它不应该写的内存。