由于想尝试去检测内存泄漏,因此使用了最常见的工具Valgrind

方法

执行以下命令即可,将输出的log进行重定位,执行对应可执行程序

valgrind --tool=memcheck --leak-check=full --log-file=valgrind.log ./build/bin/suffix data/test2.fa

输出

显示使用了Memcheck工具,用于检测内存,是一个Valgrind自带的工具,以及运行的指令和Parend PID

==139216== Memcheck, a memory error detector
==139216== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==139216== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==139216== Command: ./build/bin/suffix data/test2.fa
==139216== Parent PID: 133038

根据询问Qwen2.5-Max,我们可以得出Memcheck有以下功能

  • 检测未初始化的内存访问 (如使用未初始化的变量)
  • 检测内存越界访问 (如数组越界、缓冲区溢出)
  • 检测内存泄漏 (如未释放的 malloc/new 分配的内存)
  • 检测重复释放(double free)或非法释放(如释放栈内存)

以下是实际的检测结果

==139216== Warning: set address range perms: large range [0x5210040, 0x40bbce2c) (undefined)
==139216== Invalid read of size 4
==139216==    at 0x114ACC: SuffixAutomation::judge_len_range(int, int) (in /home/hasee/bio/code/suffix/build/bin/suffix)
==139216==    by 0x114BF4: void SuffixAutomation::get_right_index(int)::{lambda(auto:1&&, int)#1}::operator()<{lambda(auto:1&&, int)#1}&>({lambda(auto:1&&, int)#1}&, int) const (in /home/hasee/bio/code/suffix/build/bin/suffix)
==139216==    by 0x114978: SuffixAutomation::get_right_index(int) (in /home/hasee/bio/code/suffix/build/bin/suffix)
==139216==    by 0x120950: solve(std::basic_ofstream<char, std::char_traits<char> >&, unsigned char*, int, Param const&) (in /home/hasee/bio/code/suffix/build/bin/suffix)
==139216==    by 0x1139FD: main (in /home/hasee/bio/code/suffix/build/bin/suffix)
==139216==  Address 0x4114e33c is 4 bytes before a block of size 262,144 alloc'd

可以发现展开了整个调用栈,错误是读取了一个分配好的Block之前的4个字节,因此导致了越界,最后还说明了是分配的位置是一个大小为262144字节的vector

接着可以查看对于内存泄漏的检测

==1079975== Memcheck, a memory error detector
==1079975== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==1079975== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==1079975== Command: ./build/bin/suffix data/test2.fa
==1079975== Parent PID: 133038
==1079975== 
==1079975== Warning: set address range perms: large range [0x5210040, 0x40bbce2c) (undefined)
==1079975== 
==1079975== HEAP SUMMARY:
==1079975==     in use at exit: 1,000,001,476 bytes in 2 blocks
==1079975==   total heap usage: 188,348 allocs, 188,346 frees, 1,019,210,874 bytes allocated
==1079975== 
==1079975== 1,000,001,004 bytes in 1 blocks are possibly lost in loss record 2 of 2
==1079975==    at 0x4846FA3: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==1079975==    by 0x10BC0A: return_read(_IO_FILE*) (in /home/hasee/bio/code/suffix/build/bin/suffix)
==1079975==    by 0x11391E: main (in /home/hasee/bio/code/suffix/build/bin/suffix)
==1079975== 
==1079975== LEAK SUMMARY:
==1079975==    definitely lost: 0 bytes in 0 blocks
==1079975==    indirectly lost: 0 bytes in 0 blocks
==1079975==      possibly lost: 1,000,001,004 bytes in 1 blocks
==1079975==    still reachable: 472 bytes in 1 blocks
==1079975==         suppressed: 0 bytes in 0 blocks
==1079975== Reachable blocks (those to which a pointer was found) are not shown.
==1079975== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==1079975== 
==1079975== For lists of detected and suppressed errors, rerun with: -s
==1079975== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

经过GPT的解析,可以发现这里检测数量内存泄漏,一共进行了188,348次内存分配和188,346次内存释放,总共分配了1,019,210,87字节,说明有两次内存分没有释放。

而后还说明了内存泄露的具体情况:

  • 可能泄漏(possibly lost): 1,000,001,004字节(接近1GB
  • 泄漏发生在return_read(_IO_FILE*) 函数中
  • 调用堆栈:main函数 -> return_read函数 -> operator new

于是找到对应函数进行查看内存释放情况即可。