zoukankan      html  css  js  c++  java
  • C++ 复制控制 Copy Control 示例, 及内存泄漏检测工具 Valgrind 的简单使用

    主页: http://valgrind.org/

    文档下载:http://valgrind.org/docs/download_docs.html

    简单使用:  http://cs.ecs.baylor.edu/~donahoo/tools/valgrind/

    valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes ./test

    Valgrind is an instrumentation framework for building dynamic analysis tools. There are Valgrind tools that can automatically detect many memory management and threading bugs, and profile your programs in detail. You can also use Valgrind to build new tools.

    The Valgrind distribution currently includes six production-quality tools: a memory error detector, two thread error detectors, a cache and branch-prediction profiler, a call-graph generating cache and branch-prediction profiler, and a heap profiler. It also includes three experimental tools: a heap/stack/global array overrun detector, a second heap profiler that examines how heap blocks are used, and a SimPoint basic block vector generator. It runs on the following platforms: X86/Linux, AMD64/Linux, ARM/Linux, PPC32/Linux, PPC64/Linux, S390X/Linux, MIPS/Linux, ARM/Android (2.3.x and later), X86/Android (4.0 and later), X86/Darwin and AMD64/Darwin (Mac OS X 10.6 and 10.7, with limited support for 10.8).

    当源代码使用 -g 选项编时,valgrind 可以定位出现内存泄漏的行号, 无-g选项也是可以的。

    如:  g++ -g HasPtr.cxx

    /*
     * HasPtr.cxx
     * 
     */
    #include <iostream>
    using namespace std;
    
    class HasPtr{
    public:
    	//默认构造函数
    	HasPtr(){
    		cout<<"HasPtr默认构造函数被调用"<<hex<<this<<dec<<endl;
    		//pval = new int(0); //#1
    		pval = NULL;
    		val = 0;
    	}
    	//正常构造函数
    	HasPtr(const int * rhs,int ival = 0){
    		cout<<"HasPtr构造函数被调用,this@"<<hex<<this<<dec<<endl;
    		pval = new int(*rhs);
    		val = ival;
    	}
    	//复制构造函数
    	HasPtr(const HasPtr & rhs){
    		cout<<"HasPtr复制构造函数被调用,this@"<<hex<<this<<dec<<endl;
    		pval = new int(*rhs.pval);
    		val = rhs.val;
    	}
    	//赋值操作符
    	HasPtr &  operator = (const HasPtr & rhs){
    		cout<<"HasPtr operator = 函数被调用,this@"<<hex<<this<<dec<<endl;
    		//*pval = *rhs.pval;	//#1处,在默认构造中也有分配指针所指对象,则直接赋值
    		
    		/***************************************************/
    		delete pval;			//删除NULL指针是安全的,注释掉这行,可以查看到内存泄漏
    		/***************************************************/
    		
    		pval = new int(*rhs.pval);
    		val = rhs.val;
    		return *this;
    	}
    	
    	//构造函数
    	~HasPtr(){
    		delete pval;
    		cout<<"HasPtr析造函数被调用,this@"<<hex<<this<<dec<<endl;
    	}
    	
    	void to_str(){
    		cout<<"HasPtr.to_str() called:val="<<val
    		<<",*pval="<<*pval
    		<<",pval="<<hex<<pval<<
    		",this@"<<hex<<this<<dec<<endl<<endl;
    	}
    //private:
    	int val,*pval;
    };
    
    int main(int argc, char **argv)
    {
    	int i =110;
    	HasPtr p1(&i,2);
    	p1.to_str();
    	
    	//HasPtr p2(&i,2);	//常规构造函数
    	//HasPtr p2(p1);	//复制构造函数
    	//HasPtr p2 = p1;	//复制构造函数
    	
    	HasPtr p2;			//默认构造
    	p2 = p1;			//赋值操作符
    	
    	p2.to_str();
    	
    	p2.val *=2;
    	*p2.pval *=2;
    	
    	cout<<"########## after change ##########"<<endl;
    	p1.to_str();
    	p2.to_str();
    	
    	p1 = p2;
    	cout<<"######## p1 = p2 ############"<<endl;
    	
    	p1.to_str();
    	p2.to_str();
    	return 0;
    }
    

    检测结如下:

    spark@spark-vbox:~/workspace/Cpp$ valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes ./a.out
    ==5837== Memcheck, a memory error detector
    ==5837== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
    ==5837== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
    ==5837== Command: ./a.out
    ==5837== 
    HasPtr构造函数被调用,this@0xbee6204c
    HasPtr.to_str() called:val=2,*pval=110,pval=0x4323028,this@0xbee6204c
    
    HasPtr默认构造函数被调用0xbee62054
    HasPtr operator = 函数被调用,this@0xbee62054
    HasPtr.to_str() called:val=2,*pval=110,pval=0x4323060,this@0xbee62054
    
    ########## after change ##########
    HasPtr.to_str() called:val=2,*pval=110,pval=0x4323028,this@0xbee6204c
    
    HasPtr.to_str() called:val=4,*pval=220,pval=0x4323060,this@0xbee62054
    
    HasPtr operator = 函数被调用,this@0xbee6204c
    ######## p1 = p2 ############
    HasPtr.to_str() called:val=4,*pval=220,pval=0x4323098,this@0xbee6204c
    
    HasPtr.to_str() called:val=4,*pval=220,pval=0x4323060,this@0xbee62054
    
    HasPtr析造函数被调用,this@0xbee62054
    HasPtr析造函数被调用,this@0xbee6204c
    ==5837== 
    ==5837== FILE DESCRIPTORS: 3 open at exit.
    ==5837== Open file descriptor 2: /dev/pts/2
    ==5837==    <inherited from parent>
    ==5837== 
    ==5837== Open file descriptor 1: /dev/pts/2
    ==5837==    <inherited from parent>
    ==5837== 
    ==5837== Open file descriptor 0: /dev/pts/2
    ==5837==    <inherited from parent>
    ==5837== 
    ==5837== 
    ==5837== HEAP SUMMARY:
    ==5837==     in use at exit: 4 bytes in 1 blocks
    ==5837==   total heap usage: 3 allocs, 2 frees, 12 bytes allocated
    ==5837== 
    ==5837== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
    ==5837==    at 0x402B9B4: operator new(unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
    ==5837==    by 0x8048B86: HasPtr::HasPtr(int const*, int) (HasPtr.cxx:20)
    ==5837==    by 0x8048821: main (HasPtr.cxx:58)
    ==5837== 
    ==5837== LEAK SUMMARY:
    ==5837==    definitely lost: 4 bytes in 1 blocks
    ==5837==    indirectly lost: 0 bytes in 0 blocks
    ==5837==      possibly lost: 0 bytes in 0 blocks
    ==5837==    still reachable: 0 bytes in 0 blocks
    ==5837==         suppressed: 0 bytes in 0 blocks
    ==5837== 
    ==5837== For counts of detected and suppressed errors, rerun with: -v
    ==5837== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
    

     它可以检测出在哪一行分配的内存没有被释放,不能给出合适的应该释放的位置,这确实难办到,分析时要注意。

  • 相关阅读:
    日志类
    sql查询数据并导出问题
    高并发系统设计(十七):【系统架构】微服务化后,系统架构要如何改造?
    高并发系统设计(十五):【消息队列】如何降低消息队列系统中消息的延迟?
    高并发系统设计(十四):【消息队列】如何消息不丢失?并且保证消息仅仅被消费一次?
    高并发系统设计(十三):消息队列的三大作用:削峰填谷、异步处理、模块解耦
    高并发系统设计(十二):【缓存的正确使用姿势】缓存穿透了怎么办?如何最大程度避免缓存穿透
    高并发系统设计(十一):【缓存的正确使用姿势】缓存如何做到高可用?
    ThinkPad X1 Carbon无法识别第二屏幕
    如何设置两个TPLink路由器桥接
  • 原文地址:https://www.cnblogs.com/wucg/p/3082160.html
Copyright © 2011-2022 走看看