Valgrind

Valgrind

fetch150zy

一些最棘手的 C 错误来自内存管理不善:分配错误的大小、使用未初始化的指针、在释放内存后访问内存、溢出缓冲区等,使用valgrind可以帮助我们跟踪这些潜在的错误

Valgrind 内存检查

一、内存错误与内存泄露

Valgrind会报告两种类型的问题

内存错误

  • 读取未初始化的内存
  • 写入超过一段内存结尾
  • 访问释放的内存

内存泄露

  • 程序动态分配内存忘记释放

二、在 Valgrind 下运行程序

Valgrind 在你的可执行文件上运行

1
$ valgrind ./exec

带命令函参数

1
$ valgrind ./exec argv[1] ... 

三、查找内存错误

常见内存错误

  • Invalid read/write of size X

    读取/写入无效的 X 字节内存。常见原因包括访问超出堆块的末尾、访问已释放的内存或访问未分配的区域

    (例如使用未初始化的指针)

  • Use of uninitialised value or Conditional jump or move depends on uninitialised value(s)

    程序读取以前未写入的内存位置的值,即使用随机垃圾

    若想追踪未初始化的值,使用 Valgrind --track-origins=yes

  • Source and destination overlap in memcpy()

    试图将数据从一个位置复制到另一个位置,并且要读取的范围与要写入的范围相交

    使用memcpy可能导致结果混乱,此处应正确使用memmove

  • Invalid free()

    该程序试图多次释放非堆地址或释放同一块

四、查找内存泄露

泄露情况分类

  • definitely lost:从未释放的堆分配内存,程序不再拥有指针
  • indirectly lost:间接丢失,从未释放的堆分配内存,指向它的唯一指针也丢失了,比如链表后面结点的丢失
  • possibly lost:可能丢失,从未释放的堆分配内存,无法确定是否存在指针
  • still reachable:仍然可访问,从未释放的堆分配内存,程序退出时仍有指针

鉴于泄漏通常不会导致错误,而不正确的释放会导致错误,我们建议您在程序完成之前不要担心释放内存。

然后,您可以返回并适当地释放您的内存,确保每一步的正确性

如果您需要更多信息,您需要包括选项--leak-check=full--show-leak-kinds=all

使用-g标志进行编译,valgrind所以能够准确地告诉我们在我们的程序中创建泄漏的位置