4

Valgrind のmemcheckツールを実行すると、数十万 (またはそれ以上、Valgrind は 100K で切り捨てられるため) の小さな無効な読み取りステートメントを取得することがよくあります。

==32027== Invalid read of size 1
==32027==    at 0x3AB426E26A: _IO_default_xsputn (in /lib64/libc-2.5.so)
==32027==    by 0x3AB426CF70: _IO_file_xsputn@@GLIBC_2.2.5 (in /lib64/libc-2.5.so)
==32027==    by 0x3AB42621FA: fwrite (in /lib64/libc-2.5.so)
==32027==    by 0x4018CA: STARCH_gzip_deflate (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32027==    by 0x401F48: compressFileWithGzip (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32027==    by 0x4028B5: transformInput (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32027==    by 0x402F12: main (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32027==  Address 0x7febb9b3c is on thread 1's stack

これらのステートメントは、アプリケーション (" ") の外部にある関数の呼び出しを参照してstarchおり、 の一部であると思われますlibc。これは私が気にする必要があるものですか?

編集

fwrite呼び出しを変更して 1 バイトを削除すると、gzip ストリームが破損します。元のコードは次のとおりです。

int STARCH_gzip_deflate(FILE *source, FILE *dest, int level) {                                                                                                                                                                                                              

    int ret, flush;                                                                                                                                                                                                                                                         
    unsigned have;                                                                                                                                                                                                                                                          
    z_stream strm;                                                                                                                                                                                                                                                          
    unsigned char in[STARCH_Z_CHUNK];                                                                                                                                                                                                                                       
    unsigned char out[STARCH_Z_CHUNK];                                                                                                                                                                                                                                      

    /* initialize deflate state */                                                                                                                                                                                                                                            
    strm.zalloc = Z_NULL;                                                                                                                                                                                                                                                   
    strm.zfree = Z_NULL;                                                                                                                                                                                                                                                    
    strm.opaque = Z_NULL;                                                                                                                                                                                                                                                   

    /* deflateInit2 allows creation of archive with gzip header, i.e. a gzip file */                                                                                                                                                                                        
    /* cf. http://www.zlib.net/manual.html */                                                                                                                                                                                                                               
    ret = deflateInit2(&strm, level, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY);                                                                                                                                                                                           
    if (ret != Z_OK)                                                                                                                                                                                                                                                        
        return ret;                                                                                                                                                                                                                                                         

    /* compress until end of file */                                                                                                                                                                                                                                        
    do {                                                                                                                                                                                                                                                                    
        strm.avail_in = fread(in, 1, STARCH_Z_CHUNK, source);                                                                                                                                                                                                               
        if (ferror(source)) {                                                                                                                                                                                                                                               
            (void)deflateEnd(&strm);                                                                                                                                                                                                                                        
            return Z_ERRNO;                                                                                                                                                                                                                                                 
        }                                                                                                                                                                                                                                                                   
        flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;                                                                                                                                                                                                                       
        strm.next_in = in;                                                                                                                                                                                                                                                  

        do {                                                                                                                                                                                                                                                                
            strm.avail_out = STARCH_Z_CHUNK;                                                                                                                                                                                                                                
            strm.next_out = out;                                                                                                                                                                                                                                            
            ret = deflate(&strm, flush);                                                                                                                                                                                                                                    
            assert(ret != Z_STREAM_ERROR);                                                                                                                                                                                                                                  
            have = STARCH_Z_CHUNK - strm.avail_out;     

            /* invalid read happens here */                                                                                                                                                                                                                    
            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {                                                                                                                                                                                                       
                (void)deflateEnd(&strm);                                                                                                                                                                                                                                    
                return Z_ERRNO;                                                                                                                                                                                                                                             
            }                                                                                                                                                                                                                                                               
        } while (strm.avail_out == 0);                                                                                                                                                                                                                                      
        assert(strm.avail_in == 0);                                                                                                                                                                                                                                         

    } while (flush != Z_FINISH);                                                                                                                                                                                                                                            
    assert(ret == Z_STREAM_END);                                                                                                                                                                                                                                            

    /* clean up and return */                                                                                                                                                                                                                                               
    (void)deflateEnd(&strm);                                                                                                                                                                                                                                                
    return Z_OK;                                                                                                                                                                                                                                                            
}   

編集2

私は問題を見ていると思います。私は持っていて、持っin[STARCH_Z_CHUNK]ていませんin[STARCH_Z_CHUNK + 1](そして同様にout[])。freadfwriteステートメントの両方を で調整すると-1、これらのステートメントが得られないように見えますが、に固有のandInvalid read of size 1はまだ多く見られます。Invalid read of size 48zlib

==32624== Invalid read of size 4
==32624==    at 0x3AB5206455: deflateInit2_ (in /usr/lib64/libz.so.1.2.3)
==32624==    by 0x40180E: STARCH_gzip_deflate (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32624==    by 0x401F48: compressFileWithGzip (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32624==    by 0x402C03: transformInput (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32624==    by 0x402F12: main (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32624==  Address 0x7feafde38 is on thread 1's stack

編集3

-g前述のように、行番号をエラーに関連付ける再コンパイルを行っています。

しかし、私は単純な変数を実行しているだけですstrncpyargv[]たとえば、次のようになります。

strncpy(uniqTag, argv[2], strlen(argv[2]) + 1);

これにより、null で終わるargv[2]文字列が にコピーされますがuniqTagvalgrindこれはエラーとしてマークされます。

編集4

エラーメッセージは次のとおりです。

==3682== Invalid read of size 1
==3682==    at 0x4A081C1: strncpy (mc_replace_strmem.c:329)
==3682==    by 0x4022F1: parseCommandLineInputs (starch.c:589)
==3682==    by 0x402F20: main (starch.c:46)
==3682==  Address 0x7fedffe11 is on thread 1's stac

関連する 2 行を次に示します。valgrind は、2 行目が無効な読み取りであると言っています。

uniqTag = (char *)malloc(strlen(argv[2]) + 1); 
strncpy(uniqTag, argv[2], strlen(argv[2]) + 1);

なぜならstrlen(argv[2]) + 1 > strlen(argv[2])、これは null で終わるuniqTag.

4

2 に答える 2

5

この場合、私はあなたがそうすると言います。libc 関数の引数は、プログラムから取得されます。私は推測を危険にさらし、コードにオフバイワンエラーがあり、fwriteがソースバッファーの末尾を1バイト超えて読み取るように導くと言います。

編集:

ところで、コンパイラとメモリ アロケータは通常、メモリ ブロックを特定のサイズで割り当て、ワード エッジに配置するため、このような小さなエラーは見過ごされることがよくあります (つまり、コードがクラッシュすることはありません)。これは、多くの場合、メモリ保護コードをトリガーせずにアクセスできる、要求されたバッファーの終わりを過ぎた小さな領域があることを意味します。もちろん、コンパイラ、libc、プラットフォーム、またはビット数を変更すると (たとえば、64 ビットから 32 ビットに変更すると)、コードが壊れる可能性があります。

Valgrind には libc で予想されるエラーの抑制リストがあり、通常は /usr/lib64/valgrind/default.supp または /usr/lib/valgrind/default.supp にあります。valgrind が libc で検出する問題はかなり多く、その多くはコードを最適化するための意図的なものですが、99% のケースで抑制されているため、問題を引き起こしているのはテスト済みのコードです。

EDIT2:

ほとんどのデバッグ ツールと同様に、Valgrind は、デバッグ シンボルを使用してコードをコンパイルすると、検出された問題に関する非常に有用な情報を出力することに注意してください。問題に関連する特定のコード行を示すことができます - 実際の問題がどこにあるかではないことがよくあります。GCC を使用する場合は、オプションに -g を追加するだけで、デバッグ シンボルを使用してコードをコンパイルできます。ただし、本番リリースでは、そのフラグを削除することを忘れないでください!

于 2010-11-16T21:47:13.923 に答える
1

自分のコードにたどり着くまでコール スタックをたどって、エラーの原因を探す必要があります。この場合、 valgrind が吠える原因となっ ている悪いもの (おそらく悪いもの、または書き出そうとしているバッファー) でSTARCH_gzip_deflate呼び出しているように見えます。fwriteFILE *

ただし、これは実際にはエラーではないか、あなたのエラーではない可能性があります。しかし、それはおそらくそうです。

于 2010-11-16T21:47:57.647 に答える