c++ 代码内存如何校验以及检查
本次文章使用 valgrind 对c++ 代码的内存进行校验
:
1、valgrind 安装
sudo apt install valgrind
2、如何使用 valgrind 对代码进行检查
测试代码:
#include <iostream>
#include <string>
#include <memory>
int main(int argc, char** argv){
std::string arg = argv[1];
std::cout << "arg=" << arg << std::endl;
if(arg == "lost_mem"){
// 内存泄漏
int *a = new int();
}
if(arg == "double_free"){
// double free
int * b = new int();
std::shared_ptr<int> c(b);
delete b;
}
if(arg == "free_stack"){
// 释放栈空间
int b;
int *c = &b;
delete c;
}
}
如上代码:
这个测试分别使用3个选项:
lost_mem 测试内存泄漏, 申请了 int 内存未释放
double_free 重复释放:
这里可以看出来 b 给了 shared_ptr, 但是 b 本身有调用了 delete.
所以在 shared_ptr 释放的时候就会导致 重复释放 b
free_stack 释放 栈空间,正常情况下,大部分c++ 程序员都不会犯这个错误,但是如果是使用别人的接口的时候,就有可能造成这个错误。 别人让你传指针,你将栈指针穿进去了,结果别人的代码释放了你穿进去的栈指针,就会出现这个问题。
下面我们看一下每一个的执行结果:
lost_mem
virtual-machine:~/workspace/tmp$ valgrind --leak-check=full ./test lost_mem
==15002== Memcheck, a memory error detector
==15002== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==15002== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==15002== Command: ./test lost_mem
==15002==
arg=lost_mem
==15002==
==15002== HEAP SUMMARY:
==15002== in use at exit: 4 bytes in 1 blocks
==15002== total heap usage: 3 allocs, 2 frees, 73,732 bytes allocated
==15002== # 注意看这里,报错 test.cpp:9 第9行内存泄漏4个字节
==15002== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==15002== at 0x4849013: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==15002== by 0x10A562: main (test.cpp:9)
==15002==
==15002== LEAK SUMMARY:
==15002== definitely lost: 4 bytes in 1 blocks
==15002== indirectly lost: 0 bytes in 0 blocks
==15002== possibly lost: 0 bytes in 0 blocks
==15002== still reachable: 0 bytes in 0 blocks
==15002== suppressed: 0 bytes in 0 blocks
==15002==
==15002== For lists of detected and suppressed errors, rerun with: -s
==15002== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
double_free
virtual-machine:~/workspace/tmp$ valgrind --leak-check=full ./test double_free
==14672== Memcheck, a memory error detector
==14672== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14672== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==14672== Command: ./test double_free
==14672==
arg=double_free
# 注意看这里报错显示 shared_ptr_base.h:348 free 错误,这里没有明确指出错误原因
==14672== Invalid free() / delete / delete[] / realloc()
==14672== at 0x484BB6F: operator delete(void*, unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==14672== by 0x10AED7: std::_Sp_counted_ptr<int*, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:348)
==14672== by 0x10ABC6: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (shared_ptr_base.h:168)
==14672== by 0x10A95A: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (shared_ptr_base.h:705)
==14672== by 0x10A73D: std::__shared_ptr<int, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr_base.h:1154)
==14672== by 0x10A75D: std::shared_ptr<int>::~shared_ptr() (shared_ptr.h:122)
==14672== by 0x10A5CF: main (test.cpp:16)
==14672== Address 0x4de30c0 is 0 bytes inside a block of size 4 free'd
==14672== at 0x484BB6F: operator delete(void*, unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==14672== by 0x10A5C3: main (test.cpp:15)
==14672== Block was alloc'd at
==14672== at 0x4849013: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==14672== by 0x10A590: main (test.cpp:13)
==14672==
==14672==
==14672== HEAP SUMMARY:
==14672== in use at exit: 0 bytes in 0 blocks
==14672== total heap usage: 4 allocs, 5 frees, 73,756 bytes allocated
==14672==
==14672== All heap blocks were freed -- no leaks are possible
==14672==
==14672== For lists of detected and suppressed errors, rerun with: -s
==14672== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
free_stack
virtual-machine:~/workspace/tmp$ valgrind --leak-check=full ./test free_stack
==15203== Memcheck, a memory error detector
==15203== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==15203== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==15203== Command: ./test free_stack
==15203==
arg=free_stack
# 注意看这里, test.cpp:21 free 错误,同样没有明确指出错误原因,这个就需要大家自己去研究原因了
==15203== Invalid free() / delete / delete[] / realloc()
==15203== at 0x484BB6F: operator delete(void*, unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==15203== by 0x10A607: main (test.cpp:21)
==15203== Address 0x1ffefffd90 is on thread 1's stack
==15203== in frame #1, created by main (test.cpp:4)
==15203==
==15203==
==15203== HEAP SUMMARY:
==15203== in use at exit: 0 bytes in 0 blocks
==15203== total heap usage: 2 allocs, 3 frees, 73,728 bytes allocated
==15203==
==15203== All heap blocks were freed -- no leaks are possible
==15203==
==15203== For lists of detected and suppressed errors, rerun with: -s
==15203== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
以上就是个人的一些小心得