`

Linux程序设计中由线程使用不当引起的内存泄漏

 
阅读更多

Linux程序设计中,创建线程时调用pthread_create()函数,该函数原型如下:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
其 中第二个参数attr为线程属性指针,一般情况下,我们创建线程时,若对线程属性没有特殊要求,都将此参数设为NULL,这也就使用了线程的默认属性- 非分离状态(joinable,或称可接合状态),之后,主线程必须在适当的时候调用pthread_join(),来接合(join,或等待,同步)子 线程,同时释放线程本身占用的资源;否则,线程资源将驻留内存,直到整个进程退出为止.若进程会不断的创建线程,则每创建一次线程都会导致内存资源的消 耗,很明显,这已经构成了内存泄漏!

关于这个问题,举出本人查到的佐证
1)) Linux man page里是这样讲的:
 When a joinable thread terminates, its memory resources (thread descriptor and stack) are not deallocated until another thread performs pthread_join on it. Therefore, pthread_join must be called  once  for  each joinable thread created to avoid memory leaks.
2)) <<Linux高级编程>>里是这样讲的:
可接合(需要等待)的线程,就像一个进程一样,当它执行结束时,并没有被GNU/Linux自动清理,而它的退出状态却仍在系统内挂着(这有点像僵尸进程),直到另一个线程调用pthread_join()获取其返回值时,其资源才被释放.

对于线程资源的释放,有两种实现方法:
(1) 线程创建时,默认属性是可接合的(joinable),那就需要主线程来等待,所以在创建这个线程后适当的时候就必须调用pthread_join()来等待子线程结束执行,否则就会引起内存泄漏!

在 调用pthread_create()开线程后,若线程属性是joinable,则必须调用pthread_join()来等待子线程结束执行,这是 Linux同步主线程和子线程的一个机制,但是,这并不等于说,我要在pthread_create()开线程后立即调用pthread_join()来 等待该线程结束执行,的确,那样的话跟你用普通函数调用来实现是没有区别的,你完全可以在pthread_create()开线程后去做别的事情,等你觉 得应该等待该线程结束执行时再调用pthread_join().这就是说,假如你的线程采用了默认属性joinable,你就必须在适当的时候调用 pthread_join()来同步主线程和子线程,同时释放子线程的资源(线程描述符和堆栈(thread descriptor and stack)).
假如你用了默认线程属性,即线程属性为joinable,而又没有在适当的时候调用pthread_join(),那么该线程所占用的资源便不会被释放(kind of like a zombie process),因此造成内存泄漏.
假如你不想或没有必要同步主线程和子线程,那么就把子线程属性设置为detached分离状态,那么子线程结束执行后会自行销毁其占用的资源.
(2) 将线程属性设为分离状态(detached),这个样子线程就属于自灭那种,子线程函数启动后跟主线程不再有"父子"关系(等待和被等待),退出线程时其 资源会释放.注意:创建线程时,若属性参数为NULL,则线程属性默认为可接合的(joinable,即需要主线程等待的).
可以在线程创建时将其属性设为分离状态(detached),也可在线程创建后将其属性设为分离的(detached).

#include <pthread.h>
void* thread_function (void* thread_arg)
{
pthread_exit(“Exiting from the thread_function!”);
}
int main ()
{
pthread_t thr;
void* thread_result;
   pthread_create (&thr, NULL, &thread_function, NULL);
pthread_join(thr, &thread_result);
return 0;
}
 
(2) 将线程属性设为detached的两种方法的代码框架,
<1> Example Code of Setting a Thread DETACHED(1)
   
    在线程创建时,通过属性变量设置

#include <pthread.h>
void* thread_function (void* thread_arg)
{
 pthread_exit(….);
}
int main ()
{
pthread_attr_t attr;
pthread_t thread;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&thread, &attr, &thread_function, NULL);
pthread_attr_destroy (&attr);
return 0;
}
<2> Example Code of Setting a Thread DETACHED(2)
   
    线程创建后,通过调用pthread_detach()来设置

#include <pthread.h>
void* thread_function (void* thread_arg)
{
   pthread_exit(....);
}
int main ()
{
pthread_t thread;
pthread_create (&thread, NULL, &thread_function, NULL);
pthread_detach(thread); 
return 0;
}
分享到:
评论

相关推荐

    POSIX多线程程序设计

    在深入探索 POSIX 多线程程序设计之前,我们需要了解POSIX(可移植操作系统接口)是一个定义一系列UNIX系统服务的接口标准,这些服务包括文件处理、进程控制、信号处理、定时器、多线程等,POSIX标准让编写的应用...

    linux内存检测、线程调试工具valgrint 使用手册

    Valgrind是一款功能强大的Linux下的动态程序分析框架,它提供了一系列的工具用于帮助开发者进行内存泄漏检测、多线程调试等任务。Valgrind尤其适用于C/C++程序的开发,通过其核心工具——Memcheck,可以检测到许多...

    Linux进程、线程和调度(1)

    在Linux中,内存泄漏是指程序在申请内存后未能释放或者未能正确释放,导致随着时间的推移,系统中可用的内存资源逐渐减少,最终可能导致系统运行缓慢甚至崩溃。内存泄漏的原因可能包括代码逻辑错误、资源管理不当...

    嵌入式Linux性能详解-Linux内存管理

    - **内存释放时机**:适时地释放不再使用的内存,可以避免内存泄漏,保持程序稳定运行。 #### 2.2. 动态库 动态链接库是现代操作系统中常见的库文件形式,它们可以在运行时被加载,节省内存资源。 - **共享库对...

    多线程编程材料

    多线程编程是一种编程范式,允许在一个程序内同时执行多个线程,它们可以并行执行不同的任务,也可以协作完成复杂的任务,...因此在设计多线程程序时,需要仔细考虑线程的创建、同步和终止,确保程序的正确性与高效性。

    Linux高性能服务器编程源码,linux高性能服务器编程pdf,C/C++

    4. **内存管理**:理解Linux的内存模型,包括虚拟内存、页缓存、malloc/free等内存分配机制,有助于编写内存效率高的程序,避免内存泄漏和碎片化。 5. **并发与同步**:互斥锁、信号量、条件变量等并发控制机制是...

    glibc内存管理ptmalloc源代码分析.pdf

    在实际编程中,内存管理不当可能导致内存泄漏、碎片化以及程序崩溃等问题。ptmalloc的目标就是提供高效且可靠的内存分配机制,解决这些问题。 2. 基础知识 2.1 X86平台Linux进程内存布局 进程的内存布局分为多个...

    内存池NedAllocator

    内存池NedAllocator是针对内存管理优化的一种设计,它的核心思想是预先分配一大块连续的内存,然后...理解和熟练使用NedAllocator,可以帮助开发者提高程序的性能,减少资源消耗,并降低由于内存管理不当带来的风险。

    内存读写驱动的源码(C++)

    内存读写驱动是操作系统核心部分的关键组件,它允许操作系统和其他应用程序对系统内存进行直接的读取和写入操作。在C++中实现这样的驱动需要深入理解操作系统原理、内存管理机制以及设备驱动编程技术。以下是对这个...

    内存共享进程间通信示例

    内存共享是一种有效的进程间通信(IPC,Inter...因此,在使用内存共享时,应谨慎设计同步策略,确保程序的正确性和可靠性。此外,由于共享内存资源由操作系统管理,开发者还需要关注资源泄露和管理不当可能导致的问题。

    libpthread.so.0

    合理地设计线程数量和任务分配,以及正确使用`libpthread.so.0`提供的同步机制,是实现高效多线程程序的关键。 总结,`libpthread.so.0`是Linux多线程编程的基础,理解和熟练使用它可以构建健壮、高效的并发应用...

    易语言linux内存操作源码-易语言

    在Linux环境下,使用易语言进行内存操作是一项相对高级的技术,涉及到操作系统底层的内存管理和程序执行机制。本文将深入探讨易语言在Linux环境下的内存操作源码及其相关知识点。 一、内存管理基础 在Linux系统中...

    嵌入式性能详解

    2. **共享内存**:共享内存是一种高效的进程间通信方式,但其使用不当也会导致内存泄漏和数据不一致。合理使用共享内存,可以显著提升系统的整体性能。 #### 嵌入式系统特殊考虑 1. **Cache与Buffer**:缓存和缓冲...

    java问题定位技术

    - 使用`kill -3 &lt;pid&gt;`或`gcore`在Linux/Unix系统中获取core dump,进而分析线程堆栈。 4. **IDE集成环境:** - 在Eclipse、IntelliJ IDEA等集成开发环境中,可以直接查看线程堆栈信息。 ##### 1.2 如何解读线程...

    tomcat jvm内存修改

    - **检查并修复内存泄漏**:使用工具(如 VisualVM)定位内存泄漏点,并进行修复。 #### 四、Tomcat JVM 内存调整步骤 在 Linux 和 Windows 环境下,可以通过以下步骤调整 Tomcat 的 JVM 内存: ##### 4.1 Linux ...

    Android 高级面试题及答案

    进程、线程和Linux进程在概念上有所区别,进程是指一个程序的运行实例,线程是进程中的一个执行路径,而Linux进程是操作系统级别的进程管理概念。Android系统架构由Linux内核层、运行时库、应用框架和应用四层组成。...

    Unigui 1.50.0.1481防冻结补丁

    这种问题通常由多线程管理不当、内存泄漏、资源占用过高或者程序错误引起。 1.50.0.1481防冻结补丁专注于改善这些潜在问题,可能包括以下几个方面: 1. **多线程优化**:补丁可能改进了多线程管理,确保主线程不被...

    java.net.SocketException(解决方案).md

    在Java开发中,SocketException是一个常见的网络编程异常,通常是由于网络连接问题、端口资源管理不当、端口冲突或并发线程管理不当等原因引起的。要解决这个问题,可以从以下几个方面入手: 首先,检查网络连接...

    c语言文件读写操作代码.txt

    在实际的程序设计中,应该对所有可能出错的情况都进行处理,以提高程序的健壮性。 22. 程序的可扩展性和维护性:虽然这是一个简单示例,但它展示了文件操作的基本结构,这为进一步开发更复杂的应用程序提供了基础。...

    valgrind 的安装 使用

    2. **运行 Memcheck**:使用命令 `valgrind --tool=memcheck ./testnofree` 来运行程序并检测内存泄漏。 3. **查看结果**:根据 Memcheck 输出的结果,可以看到存在 1 字节的内存泄漏。 ### 四、总结 Valgrind 是...

Global site tag (gtag.js) - Google Analytics