How to return memory pointer from argument to apply to splint

1.3k views Asked by At

I met an issue to use splint. Here is the similar code

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

static void getMem(/*@null@*/void **out, size_t size)
{

    if(out == NULL)
        return;

    *out = malloc(size);
}

int main(/*@unused@*/int argc, /*@unused@*/char *argv[])
{
    char *str = NULL;

    getMem((void **)&str, 1);
    if(str != NULL)
    {
        *str = 'a';
        (void)putchar(*str);
        free(str);
    }

    return 0;
}

splint gives warning message like this,

main.c: (in function getMem)
main.c:11:2: Function returns with possibly null storage derivable from
                parameter *out
  A possibly null pointer is reachable from a parameter or global variable that
  is not declared using a /*@null@*/ annotation. (Use -nullstate to inhibit
  warning)
   main.c:10:12: Storage *out may become null
main.c:11:2: Function returns storage out reachable from parameter not
                completely defined (**out is undefined)
  Storage derivable from a parameter, return value or global is not defined.
  Use /*@out@*/ to denote passed or returned storage which need not be defined.
  (Use -compdef to inhibit warning)
   main.c:10:12: Storage **out allocated

For argument out in function getMem, I need to check NULL pointer before use. And then return memory address. Annotation "/@out@/" can not be put before the first argument since it is used in the function. And "/@null@/" only indicates out can be null but not *out. I have no idea how to deal with it. Could anyone give some advises? Thanks in advance.

1

There are 1 answers

2
Helmut Grohne On

Ultimately you cannot express what you wish to express using splint. It simply is not possible with the given prototype. The main reason is that you'd need to tell splint, that *out is an /*@out@*/ and an /*@only@*/. Except that splint has no notion of returning /*@only@*/ storage via parameters. Whenever you place /*@only@*/ in a parameter splint assumes, that the function in question free()s the memory, but you intend to allocate here. You basically have two options now:

  • Change your function prototype in a way splint can handle. Specifically avoid returning allocated memory via parameters.
  • Relax checking for this function (e.g. by putting it in a separate, unchecked file) and write a wrapper function that has a prototype that splint can handle.