多线程编程中使用pthread_create内存泄露问题
//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内存泄露问题的更多相关文章
- Java多线程编程(2)--多线程编程中的挑战
一.串行.并发和并行 为了更清楚地解释这三个概念,我们来举一个例子.假设我们有A.B.C三项工作要做,那么我们有以下三种方式来完成这些工作: 第一种方式,先开始做工作A,完成之后再开始做工作B ...
- 关于python多线程编程中join()和setDaemon()的一点儿探究
关于python多线程编程中join()和setDaemon()的用法,这两天我看网上的资料看得头晕脑涨也没看懂,干脆就做一个实验来看看吧. 首先是编写实验的基础代码,创建一个名为MyThread的 ...
- iPhone应用中如何避免内存泄露?
如何有效控制iPhone内存管理的对象的所有权与引用计数和以及iPhone内存的自动释放与便捷方法.本文将介绍在iPhone应用中如何避免内存泄露.想了解“在iPhone应用中如何避免内存泄露”就必须 ...
- Java宝典(四)------Java中也存在内存泄露。
--Java中会存在内存泄露吗? --如果你想当然的以为Java里有了垃圾回收机制就不会存在内存泄露,那你就错了. Java里也会存在内存泄露! 我们慢慢来分析. 所谓内存泄露就是指一个不再被程序使用 ...
- 对开发中常见的内存泄露,GDI泄露进行检测
对开发中常见的内存泄露,GDI泄露进行检测 一.GDI泄露检测方法: 在软件测试阶段,可以通过procexp.exe 工具,或是通过任务管理器中选择GDI对象来查看软件GDI的对象是使用情况. 注意点 ...
- Java多线程编程中Future模式的详解
Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...
- C++ 关于MFC多线程编程中的一些注意事项 及自定义消息的处理
在多线程编程中,最简单的方法,无非就是利用 AfxBeginThread 来创建一个工作线程,看一下这个函数的说明: CWinThread* AFXAPI AfxBeginThread( AFX_T ...
- Java多线程编程中Future模式的详解<转>
Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...
- Qt多线程编程中的对象线程与函数执行线程
近来用Qt编写一段多线程的TcpSocket通信程序,被其中Qt中报的几个warning搞晕了,一会儿是说“Cannot create children for a parent that is in ...
随机推荐
- Google软件构建工具Bazel
转载Google软件构建工具Bazel FAQ 本文是我的翻译,原文在这里.欢迎转载,转载请注名本文作者和原始链接注:如果想了解Bazel的原理,可以看看我之前翻译的Google Blaze原理及使用 ...
- 【Python】Python与文本处理langid工具包的文本语言检测和歧视
1.问题的叙述性说明 使用Python文本处理.文字有时被包括中国.英语.在日本和其他语言文字,进行处理.这个时候就须要判别当前文本是属于哪个语系的. Python中有个langid工具包提供了此功能 ...
- Linux-常用命令1---对文件进行查看、复制、移动和分割
基于Linux的操作系统是一种自由和开放源代码的类UNIX操作系统. Linux的几大特点决定了它的不可代替和无法超越性: (1)免费的/开源的:(2)支持多线程/多用户: (3)安全性好; (4)对 ...
- MVC 发布到 windows2003遇到 'System.Web.WebPages.Razor 错误提示
摘自: http://blog.csdn.net/lanqiao825/article/details/7840606 http://bbs.maticsoft.com/forum.php?mod=v ...
- AngularJS应用开发思维之2:数据绑定
在声明式模板中显示数据 因为不能像jQuery一样将DOM操作混在模板里,声明式模板很快让我们变得束手束脚. 一个典型的问题:在声明式模板里怎么显示数据? 假设我们有某人的基本信息,保存在一个json ...
- 什么时候需要使用Double? double、float、decimal的区别
原文:什么时候需要使用Double? double.float.decimal的区别 float:浮点型,含字节数为4,32bit,数值范围为-3.4E38~3.4E38(7个有效位) double: ...
- 新秀nginx源代码分析数据结构篇(两) 双链表ngx_queue_t
nginx源代码分析数据结构篇(两) 双链表ngx_queue_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csdn. ...
- jQuery选中该复选框来实现/全部取消/未选定/获得的选定值
<!DOCTYPE html> <html> <head> <script type="text/javascript" src=&quo ...
- (12) MVC5 EF6 Bootstrap3
MVC5 + EF6 + Bootstrap3 (12) 新建数据 系列教程:MVC5 + EF6 + Bootstrap3 上一节:MVC5 + EF6 + Bootstrap3 (11) 排序.搜 ...
- [推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼、百战不殆)
原文:[推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼.百战不殆) [推荐]ORACLE PL/SQL编程之五: 异常错误处理(知已知彼.百战不殆) 继上三篇:ORACLE PL/S ...