2

私は最近書いた C プログラムでSplintを試し、それが与える警告を理解し、取り除こうとしています。私は理解しているが、それを削除する方法を理解できないのは、次のコード スニペットからのものです。

static MyType_t *findById(const int id)
{
    int i;

    for (i = 0; i < MY_ARR_SIZE; i++) {
            if (my_arr[i].id == NOT_SET) {
                    /* Items are sorted so that items with 
                    NOT_SET as ID are at the end of the array */
                    break;
            }
            if (my_arr[i].id == id) {
                    return &(my_arr[i]);
            }
    }
    return NULL; 
}

Splint は、関数が NULL を返す可能性があることに満足していませんが、この場合は完全に理にかなっています。

/ @nullwhenfalse@ / を使用してみましたが、関数が true/false を返す場合にのみ機能するようで、retVal を使用するようにコードを変更しようとし、/ @null@ / と / @relnull@ / の両方を試しました宣言しましたが、これらは何もしませんでした。

(ちなみに、このテーブルはわずか 20 気圧しかないため、巧妙な検索アルゴリズムを使用しても意味がありません。)

4

3 に答える 3

6

宣言の前で/*@ null @*/の使用を再確認する必要があります。

次のコンパイル可能なバージョンの例では、警告が削除されます(splint 3.1.2を使用)。

typedef struct { int id; } MyType_t;
#define NOT_SET -1
#define MY_ARR_SIZE 20
static MyType_t my_arr[MY_ARR_SIZE];

/*@null@*/ static MyType_t *findById(const int id)
{
    int i;
    for (i = 0; i < MY_ARR_SIZE; i++) {
            if (my_arr[i].id == NOT_SET) {
                    /* Items are sorted so that items with 
                    NOT_SET as ID are at the end of the array */
                    break;
            }
            if (my_arr[i].id == id) {
                    return &(my_arr[i]);
            }
    }
    return NULL;
}

int main() {
    (void)findById(10);
    return 0;
}

それでも同様の警告がある場合は、コードの別の部分に関するものでしょうか?

于 2009-11-19T11:24:21.910 に答える
1

何をするにしても、スプリント コードをソースに直接埋め込むのではなく、その機能をマクロにラップすることを強くお勧めします。

たとえば、Parrot プロジェクトでは、これらのマクロがあります。

#  define ARGIN(x)                    /*@in@*/ /*@notnull@*/
#  define ARGIN_NULLOK(x)             /*@in@*/ /*@null@*/
    /* The pointer target must be completely defined before being passed */
    /* to the function. */

#  define ARGOUT(x)                   /*@out@*/ /*@notnull@*/
#  define ARGOUT_NULLOK(x)            /*@out@*/ /*@null@*/
    /* The pointer target will be defined by the function */

そして、マクロが使用されるため、次を使用できます。

void copy_string( ARGOUT(char *target), ARGIN(const char *source ) ) ...

ARGIN() 引数の処理方法を変更したい場合は、1 か所変更します。複数のツールまたはコンパイラに対して複数の表記法をサポートすることもできます。

于 2010-03-31T21:47:34.280 に答える
1

splint -nullretあなたがやりたいことかもしれないし、そうでないかもしれないその警告を(グローバルに)押しつぶします。場合によっては、型が NULL を返すことが正しいと確信していない限り、警告が必要になることがあります。

Jerome の例をテストしたところ、その特定の関数に対する警告が消えました。

于 2009-11-19T11:28:23.653 に答える