Удаление нулевых предупреждений в Splint - PullRequest
2 голосов
/ 19 ноября 2009

Я пытался Splint с программой на C, которую я недавно написал, и пытался понять и удалить предупреждения, которые он дает. Я понимаю, но не могу понять, как его удалить из следующего фрагмента кода:

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 больших атм, поэтому нет смысла использовать умный алгоритм поиска.)

Ответы [ 3 ]

6 голосов
/ 19 ноября 2009

Вы должны дважды проверить использование / * @ null @ * / перед объявлением.

В следующей скомпилированной версии вашего примера оно удаляет предупреждение (используя шину 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;
}

Если у вас все еще есть подобное предупреждение, может ли это быть о другой части вашего кода?

1 голос
/ 01 апреля 2010

Что бы вы ни делали, я бы настоятельно рекомендовал не встраивать коды шин прямо в источник, а вместо этого обернуть эту функциональность в макрос.

Например, в проекте 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 голос
/ 19 ноября 2009

splint -nullret уничтожит это предупреждение (глобально), которое может или не может быть тем, что вы хотите сделать. В некоторых случаях, если вы не уверены, что с возвращаемым типом NULL верны, вы, вероятно, хотите предупреждение.

Я проверил пример Джерома, и он отключил предупреждение для этой конкретной функции.

...