日期:2011-09-25  浏览次数:20444 次

 

这次还是把遇到的几个问题整理一下,希望再遇到的同学能轻松解决。另外最近博客的feeds延迟更新的原因也会一起说明一下。

1.linux下创建线程导致内存泄漏
今天在外网发布了一个server之后,用top发现virt的使用量一直在涨,而且一次涨8m。于是可以断定有内存泄漏了,经过排查,最终确定原因出在多线程的问题上:
代码如下:

					1
2
3
4
5
6
					pthread_t thread_id;
int ret=pthread_create(&thread_id, NULL, flush_thread_work, (void*)&m_sql_client);
if(ret!=0){
    APPSCORE_ERROR("Thread creation failed:%d",ret);
    return ret;
}

在flush_thread_work函数内部:

					1
2
3
4
5
					void* flush_thread_work(void* args)
{
    //....do something
    return NULL;
}

代码中启动了一个线程之后,主进程就继续执行,任由新线程自生自灭了(没有调用thread_join),而主进程每隔一段时间就会拉起这样一个线程来做一些数据落地的事情。

这样的写法实际上是会造成内存泄漏的.
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.

也就说线程执行完后如果不join的话,线程的资源会一直得不到释放而导致内存泄漏!

解决方法有两种:
a.在线程执行的函数内手工释放

					1
2
3
4
5
6
					void* flush_thread_work(void* args)
{
    //....do something
    pthread_detach(pthread_self());
    return NULL;
}

b.在线程启动时,设置线程的PTHREAD_CREATE_DETACHED属性

					1
2
3
4
5
6
7
8
9
10
11
12
13
14
					pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
 
int ret=pthread_create(&thread_id, &attr, flush_thread_work, (void*)&m_sql_client);
if(ret!=0){
    //记住attr也要析构,否则又是一个内存泄漏
    pthread_attr_destroy (&attr);
    APPSCORE_ERROR("Thread creation failed:%d",ret);
    return ret;
} 
 
//记住attr也要析构,否则又是一个内存泄漏
pthread_attr_destroy (&attr);

这样问题就可以解决了。
参考资料:
解决了一个隐蔽的内存泄漏——pthread_create后没有detach导致内存持续增长

2.php的json_encode函数问题
在公司做了一个应用,是php与c++进行网络交互,所以选择了json这种比较通用的序列化格式,然而却遇到了比较奇怪的问题。
先来看如下代码(php):

					1
2
3
4
5
					$objs = array();
$objs[1] = 'a';
$objs[2] = 'b';
$objs[4] = 'd';
echo json_encode($objs)."\n";

输出的结果如下:

		{"0":"a","1":"b","3":"d"}

这样是正常的,用jsoncpp也可以正确的解析出来,php自动将$objs当作一个关联数组来生成json数据了。
然而当把代码换成如下:

					1
2
3
4
5
6
					$objs = array();
$objs[0] = 'a';
$objs[1] = 'b';
$objs[2] = 'c';
$objs[3] = 'd';
echo json_encode($objs)."\n";

则输出结果如下:

		["a","b","c","d"]

jsoncpp按照之前的解析方法是解析不出来的~
其实对php来说,这也是合理的,问题在于在php里面普通数组和关联数组都是array,而对c++来说,却存在vector和map之分,所以如果还是想要json_encode生成关联数组的格式,那么需要这样写:

					1
2
3
4
5
6
					$objs = array();
$objs[0] = 'a';
$objs[1] = 'b';
$objs[2] = 'c';
$objs[3] = 'd';
echo json_encode((object)$objs)."\n";

结果如下:

		{"0":"a","1":"b","2":"c&q