Valgrind: Valgrind によってまだ到達可能なリークが検出されました 質問する

Valgrind: Valgrind によってまだ到達可能なリークが検出されました 質問する

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

まだ到達可能「」カテゴリです。(他にも 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 行が追加されました。

munmap() により、/lib/libgcc_s-4.4.4-20100630.so.1 の 0x5296fa0-0x52af438 の syms を破棄します。

リークを修正できない場合、munmap() 行によって Valgrind が「まだ到達可能な」リークを 0 個報告する理由を少なくとも説明してくれる人はいますか?

編集:

最小限のテストサンプルを以下に示します。

#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 のリーク レポート内の「まだ到達可能」カテゴリは、「メモリ リーク」の最初の定義にのみ適合する割り当てを指します。これらのブロックは解放されませんでしたが、プログラムがそれらのメモリ ブロックへのポインターをまだ追跡していたため、解放することもできました (プログラマーが希望した場合)。

一般的に、「まだ到達可能な」ブロックについて心配する必要はありません。それらは、真実メモリリークは、通常、メモリリークの原因となります。たとえば、「まだアクセス可能な」ブロックからヒープが枯渇する可能性はありません。これは、これらのブロックは通常、1回限りの割り当てであり、プロセスの存続期間中は参照が保持されるためです。プログラムが解放されていることを確認することはできますが、全て割り当てられたメモリを解放しても、プロセスが終了した後にオペレーティングシステムがプロセスのメモリをすべて回収するため、通常は実用的な利点はありません。これとは対照的に、真実メモリ リークは、修正されないまま放置されると、プロセスが長時間実行されたときにメモリ不足になる可能性があり、あるいはプロセスが必要以上に多くのメモリを消費する原因になります。

おそらく、すべての割り当てに一致する「解放」があることを保証することが有用なのは、リーク検出ツールがどのブロックが「まだ到達可能」であるかを判断できない場合 (ただし、Valgrind はこれを実行できます)、またはオペレーティング システムが終了プロセスのメモリをすべて回収しない場合 (Valgrind がこれを実行できるように移植されているすべてのプラットフォーム) のみです。

おすすめ記事