简体   繁体   中英

C function returning a string

I tried to create a sort of toString function in C like this:

struct esploratore {
    char nome[20];
    char cognome[20];
    int nascita;
    int morte;
};

char *esploratoreToString(esploratore e) {
    char *s = (char*) malloc(50 * sizeof(char));
    snprintf(s, 50,
             "%s %s %d %d",
             e.nome, e.cognome, e.nascita, e.morte);
    return s;
}

and use it in main this way:

printf("%s", esploratoreToString(e));

it works, but the problem is: will the memory assigned by the malloc be ever freed?

is this the only solution?

char *s = esploratoreToString(e);
...
printf("%s\n\n", s);
free(s);

In your original code the memory will not be freed. This is a memory leak.

To call this function properly you'll have to do

char *s = esploratoreToString(e);
printf("%s", s);
free(s);

There is not really any way around this, if you are going to have esploratoreToString do the allocation. Dynamically allocated objects in C do not ever free themselves. (C++ is another story...)

(Of course esploratoreToString should check that malloc succeeds before proceeding...)

Yes. This is a common idiom in C: the callee allocates memory and transfers ownership to the caller. That means that the caller now is responsable for freeing the allocated block.

The memory allocated by malloc() is freed when you call free() otherwise it will be freed when the process exits. As design right now, the calling code is responsible for freeing the memory once it's done with it. Alternatively, you could redesign exploratoreToString() to a provide a buffer and it's size as an argument.

There's an alternative, in which you provide the buffer:

char *esploratoreToString(esploratore *e, char *buf, int bufsz) {
    snprintf(buf, bufsz,
             "%s %s %d %d",
             e.nome, e.cognome, e.nascita, e.morte);
    return buf;
}

...

int main()
{
    char buf[100];
    esploratore exp = {...};

    printf("%s\n", esploratoreToString(&exp, buf, sizeof buf);
}

So you can allocate it dynamically, or as an automatic stack allocated buffer.

Another alternative is to returna a pointer to a statically allocated buffer, as in:

char *esploratoreToString(esploratore *e) {
    static char buf[50];
    snprintf(buf, bufsz,
             "%s %s %d %d",
             e.nome, e.cognome, e.nascita, e.morte);
    return buf;
}

But this has the problem that it is not reentrant, and also if you need to call it twice in the same call to printf(3) (in main ) the second call will overwrite the buffer and you will get a strange behaviour due to overwritting one result with the next and printing twice the same thing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM