Should I free the dynamic allocated array after returning it from the function to another?

Consider the following function:

char* color(const char* clr, char* str) { char *output = malloc(strlen(str)+1); /* Colorize string. */ sprintf(output, "%s%s%s", clr, str, CLR_RESET); return output; } 

The above function allows you to print colorized messages in the linux terminal.

So i can write

 printf("%s", color(CLR_RED, "This is our own colorized string")); 

and you will see This is our own colorized string message in red.

I am concerned about the output string highlighted in color() . By the time the function returns the selected element (the array in our example), we need to free it (C does not have a garbage collector).

My question is: what happens to output after passing to printf() ? When we exit the printf() function, is the array still allocated? If so, how can we free him? Is there a way to write a function that does this for us?

Thanks in advance!

+6
source share
3 answers

Firstly, your code is incorrect. You call malloc with a size too small, so there will be a buffer overflow . And you forgot to test with the malloc error. You should probably enter the code:

 char *output = malloc(strlen(clr)+strlen(str)+strlen(CLR_RESET)+1); if (!output) { perror ("malloc in color"); exit(EXIT_FAILURE); } sprintf(output, "%s%s%s", clr, str, CLR_RESET); 

BTW, on some asprintf systems (which would be easier to use ). IMHO using sprintf is dangerous (you should prefer snprintf ).

Then C programming takes a lot of conventions . You should have your own (inspired by ordinary practice). I recommend exploring the existing source code with free software (like github ) for inspiration.

You may have a function that returns the malloc -ed pointer, but you need to document this convention (at least as a comment in the general header file declaring color ), and an explicit obligation to call free on its result and follow it elsewhere.

Then, in the function that calls color , you call free on the result of color .

In general, you should free specify the value of the pointer after malloc was called to get it (but, of course, take care of the alias pointers ), but only once the pointer (more precisely, the memory area it points to) is useless.

Remember to include all warnings and debugging information when compiling (therefore gcc -Wall -g when using GCC ). Use the debugger ( gdb ). Use a memory leak such as valgrind .

You should read a lot more about C dynamic memory allocation and virtual address space .

If on Linux, read also Advanced Linux Programming . And reading about Operating Systems and Garbage Collection will be helpful (at least for related concepts).

+9
source

My question is: what happens to the output after passing E ()? When we exit the printf () function, is the array still allocated? If so, how can we free him? Is there a way to write a function that does this for us?

Yes, after the color function completes, the memory allocated for output still exists. You need to save the return value of the color function and call free when you are done using it.

Yes, and as noted in another answer, the size you pass malloc is small in this case.


However, you may not use malloc at all. Declare a line in the caller code, for example.

 char someStr[100]; 

and go to your color function

 void color(char* output, const char* clr, char* str) { /* Colorize string. */ sprintf(output, "%s%s%s", clr, str, CLR_RESET); } 

There is no longer a need for malloc.

Call: color(someStr, CLR_RED, "This is our own colorized string")

+3
source

Another way is to use the global char [whatever] buffer: no need to allocate (), no need free (). The color () functions always return this buffer. The only problem, which may not be the problem, is that color () will not be re-selected and should only be called once for each statement.

 char g_color_buf[200]; char* color(const char* clr, char* str) { sprintf(g_color_buf, "%s%s%s", clr, str, CLR_RESET); return g_golor_buf; } 

UPDATE : from the comment below, it is even better to declare g_color_buf [] as static inside the function itself, rather than polluting the global namespace. This does not cure other problems, but, in any case, better.

As stated above, this procedure cannot be used in expressions such as:

 printf("%s %s", color(CL_WHITE, "Result:"), color(CL_RED, "Error")); 

because the second call to color () will destroy the work done by the first call.

Finally, in order to answer your question (necessary, because otherwise someone might say "you did not answer"), the memory highlighted in color () in your code example will remain there until you (no one else) release It. Given the average, normal use that you apparently want, it would be inconvenient to write many times:

 tmp = color(CL_RED, "hello"); printf("%s", tmp); free(tmp); 

The decision to use the global buffer for transmission by color () and, possibly, is accompanied by its size, for example:

 printf("%s", color(buffer1, CL_RED, "Hello")); --or-- printf("%s", color(buffer2, sizeof(buffer2), CL_RED, "HelloHello")); 

certainly the most correct, but boring. Well, it's not boring if you want to dial!

0
source

Source: https://habr.com/ru/post/1015302/