ホームページ  >  記事  >  php教程  >  Linux、phpのjson_encodeなどでスレッドを作成するとメモリリークが発生します。

Linux、phpのjson_encodeなどでスレッドを作成するとメモリリークが発生します。

WBOY
WBOYオリジナル
2016-06-21 08:51:09937ブラウズ

今回は、私が遭遇した問題のいくつかを整理し、再び遭遇する学生が簡単に解決できることを願っています。また、最近ブログフィードの更新が遅れている理由も併せて解説します。

1. Linux でスレッドを作成するとメモリ リークが発生します
今日、外部ネットワーク上にサーバーを解放した後、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;
}

flash_thread_work 関数内:

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

コード内でスレッドが開始された後、メイン プロセスは実行を継続し、新しいスレッドをそのままにしておきます (thread_join は呼び出されません)。メイン プロセスは、データを処理するために時々そのようなスレッドを呼び出します。着陸。

この書き方では実際にメモリリークが発生します。
この問題は Linux の man ページで説明されています:

結合可能なスレッドが終了すると、別のスレッドがそのスレッドに対して pthread_join を実行するまで、そのメモリ リソース (スレッド記述子とスタック) は割り当て解除されません。そのため、メモリ リークを避けるために、作成された結合可能なスレッドごとに pthread_join を 1 回呼び出す必要があります。

つまり、スレッドの実行後に参加しないと、スレッドのリソースが解放されず、メモリ リークが発生します。

解決策は 2 つあります:
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 後にデタッチされないため、メモリが増加し続けます

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 では通常の配列と連想配列は両方とも配列ですが、C++ ではベクトルとマップがあるため、それでも 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. このブログのフィードが遅れて更新されない理由
私は feedsky のフィード更新に非常に不満を持っていたので、オンラインの慣例に従い、feed.vimer.cn を確立しました。このブログが置かれているドメイン名スペースには、ドメイン名に基づいてサブディレクトリ (フィード) が自動的に作成され、.vimer.cn が変更されます。このディレクトリ内の 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 のデフォルトのフィード リンクは http://vimer.cn/feed/rss2 であり、/feed/rss2 はサブディレクトリに解析され、自動的に http://feed にジャンプします。 feedsky .com/vimer なので、feedsky は http://feed.feedsky.com/vimer にリンクされているフィードを読み続けますが、もちろん新しいデータはありません。 。

結局、この方法は放棄されたようですが、feedsky は本当に不当な扱いを受けたようです~~~

以上、最近のまとめでした~



声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。