Heim  >  Artikel  >  php教程  >  linux下创建线程内存泄漏,php的json_encode等

linux下创建线程内存泄漏,php的json_encode等

WBOY
WBOYOriginal
2016-06-21 08:51:09939Durchsuche

 

这次还是把遇到的几个问题整理一下,希望再遇到的同学能轻松解决。另外最近博客的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","3":"d"}

3.本博feed延迟不更新的原因
之前由于对feedsky的feed更新十分不满,所以参考网上的做法,建立了一个feed.vimer.cn,而本博所在的域名空间会自动根据域名创建一个子目录 - feed,修改这个目录下的.htaccess文件如下:

					1
2
3
4
5
					<ifmodule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule . http://feed.feedsky.com/vimer [L]
</ifmodule>

那么当访问 feed.vimer.cn 时,会自动跳转到 http://feed.feedsky.com/vimer。
然而我忽略了一个问题,那就是wordpress默认的feed链接是 http://vimer.cn/feed/rss2,而/feed/rss2会被解析成子目录,从而自动跳转到 http://feed.feedsky.com/vimer ,所以feedsky就会不停的读 http://feed.feedsky.com/vimer 这个链接的feed,当然不会有任何新数据。。

所以最后还是把这种方式废弃掉了,看来真是冤枉了feedsky呀~~~

OK,最近的总结就这么多~



Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn