多線程導致的內存泄漏

Joinable threads VS Detached threads

線程有兩種運行模式:

  • Joinable Mode
  • Detached Mode

Joinable Thread & pthread_join()

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
 
#include <unistd.h>
 
void * threadFunc(void * arg)
{
	std::cout << "Thread Function :: Start" << std::endl;
	// Sleep for 2 seconds
	sleep(2);
	std::cout << "Thread Function :: End" << std::endl;
	// Return value from thread
	return new int(6);
}
 
int main()
{
	// Thread id
	pthread_t threadId;
 
	// Create a thread that will funtion threadFunc()
	int err = pthread_create(&threadId, NULL, &threadFunc, NULL);
	// Check if thread is created sucessfuly
	if (err)
	{
		std::cout << "Thread creation failed : " << strerror(err);
		return err;
	}
	else
		std::cout << "Thread Created with ID : " << threadId << std::endl;
	// Do some stuff
 
	void * ptr = NULL;
	std::cout << "Waiting for thread to exit" << std::endl;
	// Wait for thread to exit
	err = pthread_join(threadId, &ptr);
	if (err)
	{
		std::cout << "Failed to join Thread : " << strerror(err) << std::endl;
		return err;
	}
 
	if (ptr)
		std::cout << " value returned by thread : " << *(int *) ptr
				<< std::endl;
 
	delete (int *) ptr;
	return 0;
}

Detached Thread & pthread_detach()

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
 
#include <unistd.h>
 
void * threadFunc(void * arg)
{
	std::cout << "Thread Function :: Start" << std::endl;
	std::cout << "Thread Function :: End" << std::endl;
	// Return value from thread
	return NULL;
}
 
int main()
{
	// Thread id
	pthread_t threadId;
 
	// Create a thread that will funtion threadFunc()
	int err = pthread_create(&threadId, NULL, &threadFunc, NULL);
	// Check if thread is created sucessfuly
	if (err)
	{
		std::cout << "Thread creation failed : " << strerror(err);
		return err;
	}
	else
		std::cout << "Thread Created with ID : " << threadId << std::endl;
	// Do some stuff
 
	err = pthread_detach(threadId);
	if (err)
		std::cout << "Failed to detach Thread : " << strerror(err) << std::endl;
 
	// Sleep for 2 seconds because if main function exits, then other threads will
	// be also be killed. Sleep for 2 seconds, so that detached exits by then
	sleep(2);
 
	std::cout << "Main function ends " << std::endl;
	return 0;
}

多線程導致的內存泄漏

#include<stdio.h>
#include<pthread.h>
void run() {
   pthread_exit(0);
}

int main () {
   pthread_t thread;
   int rc;
   long count = 0;
   while(1) {
      if(rc = pthread_create(&thread, 0, run, 0) ) {
         printf("ERROR, rc is %d, so far %ld threads created\n", rc, count);
         perror("Fail:");
         return1;
      }
      count++;
   }
   return 0;
}

編譯運行一下:

[root@server ~]# cc -lpthread thread.c -o thread
[root@server ~]# ./thread

ERROR, rc is 12, so far 304 threads created
Fail:: Cannot allocate memory

error code 是 12,啥意思呢,perror函數幫我們打印出其含義:Cannot allocate memory
。很顯然,內存不夠了。

看看上面的代碼發現,創建的每一個線程既沒有調用pthread_join讓主線程等待創建出來的線程退出以便清理其佔用的棧空間,也沒有用pthread_detach讓線程自動清理佔用的空間。所有線程執行完後佔用空間不釋放,最終導致內存不足,造成了所謂的內存泄漏。

檢測泄漏

在調用pthread_create時候如果不設定線程的 stack size,那麼 pthread_create 會使用 ulimit -s 中設置的大小作爲 stack size。

查看設置:

$ ulimit -s
8192

表示 8192KB,也就是 8MB。
grep 8192 一下 pmap 的輸出,然後 count 一下,就是進程所有的 thread 數(包括正在跑的進程和已經結束的 joinable 線程)。

pmap PID | grep 8192 | wc -l

而 通過:

ls /proc/PID/task | wc -l

得到的是正在運行的線程數。

對比一下兩者,如果前者一直比後者大,那麼可以考慮是 線程泄漏了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章