2

C を再学習splintし、ソース コードのテストに使用しています。

私は次のことをしようとしています:

  • 「コンストラクター」関数で構造体を作成する
  • 構造体のメモリを解放する「デストラクタ」関数で構造体を破壊します。

ただし、スプリントを使用してコードをテストすると、デストラクタ内の一時ストレージに関連する警告が表示され、デストラクタを呼び出した後にメモリ リークが発生します。

(a) コードのメモリ リークについて splint が正しいかどうか (そうではないと思います)、(b) コードを修正するか、splint に自分のしていることを理解させるにはどうすればよいか、疑問に思っています。

とにかく、ここにコードがあります:

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

// define the structure
struct Boring {
    int amount;
};

// the creator
static struct Boring *Boring_create(int amount) {
    struct Boring *really = malloc(sizeof(struct Boring));
    assert(really != NULL);
    really->amount=amount;
    return really;
}

// the destroyer
static void Boring_destroy(struct Boring *really) {
    assert( really != NULL );
    // free the memory of the Boring structure
    free(really);
}

int main( /*@unused@*/ int argc, /*@unused@*/ char *argv[]) {
    int amount = 5;
    struct Boring *tv = Boring_create(amount);
    printf("The TV is boring level %d\n",tv->amount);

    // destroy the tv!
    Boring_destroy(tv);

    printf("The TV is now boring level %d\n",tv->amount);
    return 0;
}
/* Output */
/*
* $> ./destroytv
* The TV is boring level 5
* The TV is now boring level -538976289 (or 0 depending on OS/compiler)
*/

コードはコンパイルされ、gcc で正常に実行されます。

ただし、スプリントを使用してテストすると、スプリントは次の警告を発行します。

$> splint boringtv.c
destroytv.c: (in function Boring_destroy)    
destroytv.c: Implicitly temp storage really passed as only param: free (really)
 Temp storage (associated with a formal parameter) is transferred to a new non-temporary reference. The storage may be released or new aliases crated. (Use -temptrans to inhibit warning)
destroytv.c: (in function main)
destroytv.c: Fresh storage tv not released before return
 A memory leak has been detcted. Storage allocated locally is not released before the last reference to it is lost (use -mustfreefresh to inhibit warning)
 Fresh storage tv created

最初の警告は、考えれば考えるほどわからなくなります。しかし、そのマニュアルについての適切な質問を正当化するのに十分なほどマニュアルを読んでいません。

メモリ リークに関する 2 番目の警告は、メモリが別の場所で解放されていることを splint が認識していないようです。これは私には奇妙に思えます。free()内で呼び出すと、警告が消えますmain

助けてくれてありがとう。警告の行番号などの詳細が役立つかどうかお知らせください。

4

1 に答える 1

3

疑わしいように、メモリリークはありません。

splintどの関数が構造体のメモリを制御する必要があるかを示すために、デストラクタ関数への入力に で注釈を付ける必要があり/*@only@*/ます。

static void Boring_destroy( /*@only@*/ struct Boring *really ) {...

これはsplint、その関数が変数を単独で制御していることを示しているため、警告を発生させることなくメモリを平和的に解放できます。

より具体的には、「indicate[s] a reference」という唯一の注釈は、それが指すオブジェクトへの唯一のポインターです。(スプリントマニュアル)

tv注釈は、元の質問で言及されている両方の警告を削除し、それらが破棄された後に使用されていることを示す警告に置き換えます。コメントで WhozCraig が述べたように、メモリが解放された後にメモリを呼び出すことは未定義の動作であり、回避する必要があるため、この新しい警告は望ましいものです。

参考文献:

于 2015-06-27T02:37:49.560 に答える