多线程导致的内存泄漏

Joinable threads VS Detached threads

线程有两种运行模式:

  • Joinable Mode
  • Detached Mode

Joinable Thread & pthread_join()

#include 
#include 
#include 
#include 
 
#include 
 
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 
#include 
#include 
#include 
#include 
 
#include 
 
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
#include
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

得到的是正在运行的线程数。

对比一下两者,如果前者一直比后者大,那么可以考虑是 线程泄漏了。

你可能感兴趣的:(理论与基础)