1. ホーム
  2. c

[解決済み] Valgrindで検出されたStill Reachable Leak。

2022-03-05 22:36:46

質問

このブロックに記載されている関数はすべてライブラリ関数です。どうすればこのメモリーリークを修正できますか?

"に記載されています。 まだ到達可能 というカテゴリがあります。(似たようなものがあと4つありますが、大きさはまちまちです)。

 630 bytes in 1 blocks are still reachable in loss record 5 of 5
    at 0x4004F1B: calloc (vg_replace_malloc.c:418)
    by 0x931CD2: _dl_new_object (dl-object.c:52)
    by 0x92DD36: _dl_map_object_from_fd (dl-load.c:972)
    by 0x92EFB6: _dl_map_object (dl-load.c:2251)
    by 0x939F1B: dl_open_worker (dl-open.c:255)
    by 0x935965: _dl_catch_error (dl-error.c:178)
    by 0x9399C5: _dl_open (dl-open.c:584)
    by 0xA64E31: do_dlopen (dl-libc.c:86)
    by 0x935965: _dl_catch_error (dl-error.c:178)
    by 0xA64FF4: __libc_dlopen_mode (dl-libc.c:47)
    by 0xAE6086: pthread_cancel_init (unwind-forcedunwind.c:53)
    by 0xAE61FC: _Unwind_ForcedUnwind (unwind-forcedunwind.c:126)

キャッチする。 私のプログラムを実行すると、メモリリークは発生しませんでしたが、Valgrindの出力に1行追加されました。

0x5296fa0-0x52af438 にある syms を破棄する。 in /lib/libgcc_s-4.4.4-20100630.so.1 munmap() によるものです。

もしリークを修正できないのなら、なぜ munmap() の行が Valgrind に 0 "still reachable" のリークを報告させるのか、誰か少なくとも説明してください。

編集する

最小限のテストサンプルです。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *runner(void *param) {
    /* some operations ... */
    pthread_exit(NULL);
}

int n;

int main(void) {

    int i;
    pthread_t *threadIdArray;

    n=10; /* for example */

    threadIdArray = malloc((n+n-1)*sizeof(pthread_t));  

    for(i=0;i<(n+n-1);i++) {
        if( pthread_create(&threadIdArray[i],NULL,runner,NULL) != 0 ) {
            printf("Couldn't create thread %d\n",i);
            exit(1);
        }
    }


    for(i=0;i<(n+n-1);i++) {
        pthread_join(threadIdArray[i],NULL);
    }

    free(threadIdArray);

    return(0);
}

で実行します。

valgrind -v --leak-check=full --show-reachable=yes ./a.out

解決方法は?

メモリリークを定義する方法は1つではありません。特に、プログラマの間でよく使われる「メモリリーク」の定義には、主に2種類あります。

しかし、多くのプログラマーは(当然ながら)、この定義に当てはまるある種のメモリーリークは、実際には何らかの問題を引き起こすものではないので、考慮されるべきではないと主張します。 真の メモリリークとは?

メモリリークをより厳密に(そしてより有用に)定義すると、「メモリが割り当てられ、かつ できない 言い換えれば、もはやポインターを持たないメモリは解放できないのです。このようなメモリは、メモリリークと呼ばれます。Valgrindでは、より厳密な定義で「メモリリーク」と呼んでいます。このタイプのリークは、特に長寿命のプロセスで、ヒープを著しく枯渇させる可能性があります。

Valgrind のリークレポート内の "still reachable" のカテゴリは、最初の定義の "memory leak" にのみ当てはまる割り当てを指します。これらのブロックは解放されませんでしたが、プログラムがそれらのメモリブロックへのポインタをまだ追跡しているので、(プログラマが望めば)解放できたかもしれません。

一般に、quot;still reachable"ブロックについて心配する必要はありません。これらは、以下のような問題を引き起こしません。 メモリリークを引き起こす可能性があります。例えば、通常、"still reachable" ブロックからヒープを使い果たす可能性はありません。これは、これらのブロックが通常1回限りの割り当てであり、プロセスのライフタイムを通じて参照が維持されるからです。このような場合、プログラムが確実に すべて が割り当てられたとしても、プロセスの終了後にオペレーティングシステムがそのプロセスのメモリをすべて回収してしまうため、通常、そうすることによる実用的なメリットはありません。これと対照的なのが 真の メモリリークを修正せずに放置しておくと、長時間稼働させたままにしておくとメモリ不足に陥る可能性があり、また、単に必要以上にメモリを消費してしまうこともあります。

おそらく、すべての割り当てが一致する "frees" を持っていることを確認することが役に立つのは、リーク検出ツールがどのブロックが "still reachable" なのかわからない場合(しかし Valgrind はこれを行うことができます)、またはオペレーティングシステムが終了プロセスのメモリをすべて取り戻さない場合(すべて Valgrind が移植されているプラットフォーム)だけでしょう。