1

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);
1
  • 2
    No, it won't be freed unless you free it in the calling function once you're done with the steing Commented Apr 2, 2020 at 14:24

4 Answers 4

2

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

Sign up to request clarification or add additional context in comments.

3 Comments

i relized it and modified the question. TY
Well, if malloc() fails, the very first byte that snprintf() writes to the resulting NULL pointer will safely crash the process on virtually all preemptive multitasking systems. Yes, it's UB, and yes, the pedantic approach is to check for it, but most software does not need to worry.
I would be more worried about the use of snprintf() over asprintf() than about the missing NULL check: Virtually any use of snprintf() has the potential to produced truncated results that may or may not make bad things happen. This class of errors is totally unnecessary and easily avoidable by using asprintf() instead. It would actually simplify the code by avoiding the malloc() call altogether.
0

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.

Comments

0

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.

Comments

0

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.

3 Comments

This version has no way of detecting when the characters did not fit in the buffer , may or may not be important to OP's use case
Of course not... but I think that's not a problem, as the question just does the same as I.
From the outside you have better environment context to decide what kind of buffer you pass down.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.