IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

最近遇到的问题整理(linux下创建线程内存泄漏,php的json_encode等)

Vimer 2011-06-02 13:40:36 累计浏览 3,191 次
本机暂存

    这次还是把遇到的几个问题整理一下,希望再遇到的同学能轻松解决。另外最近博客的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
RewriteEngine On
RewriteBase /
RewriteRule . http://feed.feedsky.com/vimer [L]

    那么当访问 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,最近的总结就这么多~

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. 使用gettext来支持PHP的多语言 (累计阅读 39,271)
  2. WordPress插件开发 -- 在插件使用数据库存储数据 (累计阅读 29,166)
  3. Paypal接口详细代码(PHP版,非API接口) (累计阅读 19,411)
  4. Linux如何统计进程的CPU利用率 (累计阅读 16,308)
  5. 我的 RHCA 之路 (累计阅读 14,016)
  6. Linux内存点滴 用户进程内存空间 (累计阅读 13,239)
  7. 我的PHP,Python和Ruby之路 (累计阅读 13,151)
  8. 给程序员新手的一些建议 (累计阅读 13,092)
  9. Linux 性能监控、测试、优化工具 (累计阅读 13,013)
  10. 关于linux内存free的一些事情 (累计阅读 12,877)