//tls5源代码:

#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include "pthread.h"

#include "TLS/Tlsconf.h"

#include "TLS/tls_api.h"

#define ERROR  -1

#define OK     0

void test_fn2(int a)

{

char  *psz = (char*)get_buf(ENUM_1, 32);

printf("thread(%u) psz: %s\n", pthread_self(), psz);

memset(psz, 0, 32);

sprintf(psz, "%u_%d", pthread_self(), a);

return;

}

void test_fn1(int a)

{

int  *reti = (int*)get_buf(ENUM_0, sizeof(int));

printf("thread(%u) reti: %d\n", pthread_self(), *reti);

(*reti)++;

test_fn2(a);

return;

}

void* test_fn_main1(void* arg)

{

int i = 0;

for (i = 0; i < 3; i++)

{

test_fn1(i);

sleep(1);

}

return;

}

int main()

{

int iRet = ERROR;

int i = 0;

pthread_t   tid;

printf("test start!\n");

for (i = 0; i < 5; i++)

{

iRet = pthread_create(&tid, NULL, test_fn_main1, NULL);

if (OK != iRet)

{

printf("pthread_create error!\n");

return ERROR;

}

//pthread_detach(tid);

}

sleep(10);

return OK;

}

//生成可执行程序:tls库见上一篇

gcc -o tls5 tlstest5.c TLS/libtls.a -lpthread -lstdc++

//用valgrind进行内存泄露监测:

valgrind -v --leak-check=full --tool=memcheck ./tls5

提示信息:

[root@localhost 20130713]# valgrind -v --leak-check=full --tool=memcheck ./tls5

…………

==31803== malloc/free: in use at exit: 720 bytes in 5 blocks.

==31803== malloc/free: 40 allocs, 35 frees, 1,220 bytes allocated.

==31803==

==31803== searching for pointers to 5 not-freed blocks.

==31803== checked 52,519,768 bytes.

==31803==

==31803==

==31803== 720 bytes in 5 blocks are possibly lost in loss record 1 of 1

==31803==    at 0x4004824: calloc (vg_replace_malloc.c:279)

==31803==    by 0x840B39: _dl_allocate_tls (in /lib/ld-2.6.so)

==31803==    by 0x9F1B35: pthread_create@@GLIBC_2.1 (in /lib/libpthread-2.6.so)

==31803==    by 0x8048ACA: main (in /mnt/hgfs/D/work/test/20130713/tls5)

==31803==

==31803== LEAK SUMMARY:

==31803==    definitely lost: 0 bytes in 0 blocks.

==31803==      possibly lost: 720 bytes in 5 blocks.

==31803==    still reachable: 0 bytes in 0 blocks.

==31803==         suppressed: 0 bytes in 0 blocks.

…………

IN SUMMARY: 16 errors from 8 contexts (suppressed: 0 from 0)主要是库里面使用了未初始化的变量(Conditional jump or move depends on uninitialised value(s)),不管它。主要问题是在malloc/free: 40 allocs, 35 frees, 1,220 bytes allocated。

查看代码及程序运行打印,malloc与free都是一一对应的,怎会出现未释放的内存块?另外,程序共创建了5个线程,每个线程中有两次malloc操作,应该10 allocs,怎会是40allocs?排查步骤如下:

步骤一:

void* test_fn_main1(void* arg)

{

int i = 0;

for (i = 0; i < 3; i++)

{

//test_fn1(i);         //注释掉该行不再调用malloc

sleep(1);

}

return;

}

步骤二:

[root@localhost 20130713]# gcc -o tls5 tlstest5.c TLS/libtls.a -lpthread -lstdc++

[root@localhost 20130713]# valgrind -v --leak-check=full --tool=memcheck ./tls5

………………

==2237== malloc/free: in use at exit: 720 bytes in 5 blocks.

==2237== malloc/free: 5 allocs, 0 frees, 720 bytes allocated.

==2237==

==2237== searching for pointers to 5 not-freed blocks.

==2237== checked 52,526,684 bytes.

==2237==

==2237==

==2237== 720 bytes in 5 blocks are possibly lost in loss record 1 of 1

==2237==    at 0x4004824: calloc (vg_replace_malloc.c:279)

==2237==    by 0x840B39: _dl_allocate_tls (in /lib/ld-2.6.so)

==2237==    by 0x9F1B35: pthread_create@@GLIBC_2.1 (in /lib/libpthread-2.6.so)

==2237==    by 0x8048ABF: main (in /mnt/hgfs/D/work/test/20130713/tls5)

==2237==

==2237== LEAK SUMMARY:

==2237==    definitely lost: 0 bytes in 0 blocks.

==2237==      possibly lost: 720 bytes in 5 blocks.

==2237==    still reachable: 0 bytes in 0 blocks.

==2237==         suppressed: 0 bytes in 0 blocks.

--2237--  memcheck: sanity checks: 2 cheap, 1 expensive

…………

我们发现,程序中即使没有调用malloc,也存在5 allocs,纵观测试代码,唯一有可能alloc的地方就只有pthread_create了。

上网查了一下,在http://blog.csdn.net/jiqiren007/article/details/5959810找到答案。

线程在创建时都会分配一些内存(valgrind里面alloc次数是怎么算的,不是很清楚!),这些内存默认情况下需要在主线程中调用pthread_join进行释放;或者可以将子线程从父线程剥离,子线程终止时会回收这些内存资源。如果不使用pthread_join或者pthread_detach,线程结束时,pthread_create产生的内存将一直存在,直到整个进程结束为止,造成内存泄露。

在pthread_create后面加上pthread_detach(tid),结果如下:

…………………………

==3206== malloc/free: in use at exit: 0 bytes in 0 blocks.

==3206== malloc/free: 40 allocs, 40 frees, 1,220 bytes allocated.

==3206==

==3206== All heap blocks were freed -- no leaks are possible.

--3206--  memcheck: sanity checks: 2 cheap, 1 expensive

--3206--  memcheck: auxmaps: 0 auxmap entries (0k, 0M) in use

--3206--  memcheck: auxmaps: 0 searches, 0 comparisons

……………………

问题解决!

从这个问题可以看出,如果大量地启动子线程,却不对子线程进行任何处理(调用pthread_join或者pthread_detach),最终有可能导致内存大量地隐秘地被蚕食。这个过程缓慢而又难以发掘,不过带来的问题却是极严重的。

多线程编程中使用pthread_create内存泄露问题的更多相关文章

  1. Java多线程编程(2)--多线程编程中的挑战

    一.串行.并发和并行   为了更清楚地解释这三个概念,我们来举一个例子.假设我们有A.B.C三项工作要做,那么我们有以下三种方式来完成这些工作:   第一种方式,先开始做工作A,完成之后再开始做工作B ...

  2. 关于python多线程编程中join()和setDaemon()的一点儿探究

    关于python多线程编程中join()和setDaemon()的用法,这两天我看网上的资料看得头晕脑涨也没看懂,干脆就做一个实验来看看吧. 首先是编写实验的基础代码,创建一个名为MyThread的  ...

  3. iPhone应用中如何避免内存泄露?

    如何有效控制iPhone内存管理的对象的所有权与引用计数和以及iPhone内存的自动释放与便捷方法.本文将介绍在iPhone应用中如何避免内存泄露.想了解“在iPhone应用中如何避免内存泄露”就必须 ...

  4. Java宝典(四)------Java中也存在内存泄露。

    --Java中会存在内存泄露吗? --如果你想当然的以为Java里有了垃圾回收机制就不会存在内存泄露,那你就错了. Java里也会存在内存泄露! 我们慢慢来分析. 所谓内存泄露就是指一个不再被程序使用 ...

  5. 对开发中常见的内存泄露,GDI泄露进行检测

    对开发中常见的内存泄露,GDI泄露进行检测 一.GDI泄露检测方法: 在软件测试阶段,可以通过procexp.exe 工具,或是通过任务管理器中选择GDI对象来查看软件GDI的对象是使用情况. 注意点 ...

  6. Java多线程编程中Future模式的详解

    Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...

  7. C++ 关于MFC多线程编程中的一些注意事项 及自定义消息的处理

    在多线程编程中,最简单的方法,无非就是利用 AfxBeginThread  来创建一个工作线程,看一下这个函数的说明: CWinThread* AFXAPI AfxBeginThread( AFX_T ...

  8. Java多线程编程中Future模式的详解<转>

    Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...

  9. Qt多线程编程中的对象线程与函数执行线程

    近来用Qt编写一段多线程的TcpSocket通信程序,被其中Qt中报的几个warning搞晕了,一会儿是说“Cannot create children for a parent that is in ...

随机推荐

  1. Android启动第三方应用程序

    主要是开始通过包名的第三方应用程序,获取的方法的包名是非常在线.不是说. 两种方式启动: 第一: Intent intent = new Intent(); intent.setClassName(& ...

  2. MVC中,视图的Layout使用

    本文目标 1.能够重用Razor模板进行页面的组件化搭建 本文目录 1.母板页_Layout.cshtml 2.用户自定义控件 3.默认Layout引用的使用(_ViewStart.cshtml) 1 ...

  3. C#快递跟踪(基于快递100深度定制)

    本文主要介绍快递跟踪的相关信息.如根据快递单号预测所属快递公司,判断快递是否已被签收,以及改良官方model后可在不用申请授权的情况下实现json,html,xml及text等多种格式以及单行多行,降 ...

  4. Android &quot;QR二维码扫描&quot;

    支持灯 扫描结果 支持 抄.分享.浏览打开(超链接) 自己主动保存扫描记录 划删除 和源代码 git: http://git.oschina.net/892642257/QRCode csdn(0分) ...

  5. 采用tcpdump攫Android网络数据包

    1 空灵的原理 tcpdump(需Root用户执行)拦截和显示发送或收到过网络连接到该机器的TCP/IP和其它数据包.简单说就监控手机进出网络数据. 2 方法优劣 2.1长处 1.手机数据包无遗漏 2 ...

  6. js模块开发

    js模块开发(一) 现在嵌入页面里面的javascript代码越来越复杂,于是可能依赖也越来越严重,使用别人开发的js也越来越多,于是在理想情况下,我们只需要实现核心的业务逻辑,其他都可以加载别人已经 ...

  7. 省钱加油(Fuel Economy)题解

    题目 农夫约翰决定去做一个环游国家旅行,为了不让他的奶牛们感到孤单,于是他决定租一辆货车带领他的奶牛们一起去旅行.这辆货车的油箱最多可以承载G 个单位的油,同时为了简化问题,规定每一个单位的油可以行使 ...

  8. nolock引发

      Sql Server之旅——终点站 nolock引发的三级事件的一些思考   曾今有件事情让我记忆犹新,那年刚来携程不久,马上就被安排写一个接口,供企鹅公司调用他们员工的差旅信息,然后我就三下五除 ...

  9. C语言库函数大全及应用实例一

    原文:C语言库函数大全及应用实例一                                 [编程资料]C语言库函数大全及应用实例一 函数名: abort 功 能: 异常终止一个进程 用 法: ...

  10. 第3章1节《MonkeyRunner源码剖析》脚本编写示例: MonkeyRunner API使用示例(原创)

    天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文“寻求合作伙伴编写<深入理解 MonkeyRunner>书籍“.但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在 ...