Francesco Tormene
Francesco Tormene

Reputation: 21

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);

Upvotes: 1

Views: 78

Answers (4)

Luis Colorado
Luis Colorado

Reputation: 12668

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.

Upvotes: 0

Kyle
Kyle

Reputation: 1

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.

Upvotes: 0

Nate Eldredge
Nate Eldredge

Reputation: 57997

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...)

Upvotes: 2

Serge Ballesta
Serge Ballesta

Reputation: 148880

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.

Upvotes: 0

Related Questions