如何优雅的写C++代码 Obotcha介绍(Valgrind内存泄露调试)

    这几天开始测试多线程的内存泄露问题,用到的工具就是Valgrind,这个工具业内还是比较出名的,用来查内存泄露,还是不错的。废话不多说,我们先从安装开始。Ubuntu环境下,运行如下命令

sudo apt-get install valgrind

安装结束以后就可以愉快的使用了。我们以下面的代码为例:

DECLARE_SIMPLE_CLASS(MyThread) IMPLEMENTS(Thread) {
public:
    void run() {
        printf("abc");
    }
};

int main() {

    MyThread t = createMyThread();
    t->start();

}

使用下面的命令:

valgrind --leak-check=full --show-reachable=yes --trace-children=yes ./mytest

运行结果:

==5152== 304 bytes in 1 blocks are possibly lost in loss record 15 of 15
==5152==    at 0x4C31B25: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5152==    by 0x40134A6: allocate_dtv (dl-tls.c:286)
==5152==    by 0x40134A6: _dl_allocate_tls (dl-tls.c:530)
==5152==    by 0x64DC227: allocate_stack (allocatestack.c:627)
==5152==    by 0x64DC227: pthread_create@@GLIBC_2.2.5 (pthread_create.c:644)
==5152==    by 0x527E50D: obotcha::_KeepAliveThread::start() (Thread.cpp:122)
==5152==    by 0x527F31B: obotcha::_Thread::_Thread(obotcha::sp<obotcha::_String>, obotcha::sp<obotcha::_Runnable>) (Thread.cpp:258)
==5152==    by 0x527EF91: obotcha::_Thread::_Thread() (Thread.cpp:243)
==5152==    by 0x114F8A: _MyThread::_MyThread() (ThreadTest.cpp:27)
==5152==    by 0x11503B: obotcha::sp<_MyThread> createMyThread<>() (ThreadTest.cpp:27)
==5152==    by 0x114E5D: main (ThreadTest.cpp:42)
==5152== 
==5152== LEAK SUMMARY:
==5152==    definitely lost: 20 bytes in 1 blocks
==5152==    indirectly lost: 0 bytes in 0 blocks
==5152==      possibly lost: 304 bytes in 1 blocks
==5152==    still reachable: 677 bytes in 13 blocks
==5152==         suppressed: 0 bytes in 0 blocks

valgrind发现pthread_create有内存泄露~~~~。额,这个当时的确让人崩溃。thread结束以后,貌似还有一小块内存一直没有被释放。这个该如何办呢?上网查了一下,原来,如果当前线程没有被设定成DETACHED的话,线程结束后,需要使用pthread_join来触发该一小段内存回收。参考之前Thread的设计,我们虽然谁然使用了一个KeepAliveThread来单独做pthread_cancel的处理,但是的确没有用pthread_join来做等待。那这样就会导致上面的问题。

参考keepAliveThread,我们又添加了一个releaseThread来触发每个需要释放的thread的join,强行释放内存即可。相关代码如下:

static void* freethreadmem(void *th) {
    _ReleaseThread *thread = static_cast<_ReleaseThread *>(th);
    thread->run();
    return nullptr;
}

_ReleaseThread::_ReleaseThread() {
    mutex = createMutex("ReleaseThreadMutex");

    cond = createCondition();

    mThreadPids = createArrayList<Uint64>();

    mStartBarrier = createAtomicInteger(0);
}

_ReleaseThread::~_ReleaseThread() {

}

void _ReleaseThread::stop() {
    Uint64 poison;
    sendRelease(poison);
    pthread_join(mTid,nullptr);
}

void _ReleaseThread::sendRelease(Uint64 t) {
    AutoMutex ll(mutex);
    mThreadPids->add(t);
    cond->notify();
}

void _ReleaseThread::start() {

    AutoMutex l(mutex);
    pthread_attr_init(&mAttr);
    pthread_create(&mTid, &mAttr, freethreadmem, this);
        
    while(mStartBarrier->orAndGet(0) == 0) {
        //wait
    }
}

在KeepAliveThread移除线程的同时,把pthread_t传递给release线程,去做join的处理

mReleaseThread->sendRelease(t); //新添加
tLocal->remove(t->toValue());

本地实测OK。关于内存泄露的检测,喷血推荐valgrind,网上说的mtrace和dmalloc建议不要去用,到处都是坑~。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值