简体   繁体   中英

Allocating memory for strings dynamically

char* test() {
    char* returnValue = "test";
    return returnValue;
}  
char* test=test();
printf("%s",test);

is it safe to use? is it the same, as

char* test {
    char* returnValue=strdup("test");
    return returnValue;
}
char* test=test();
printf("%s",test);

if yes, then should I free it later on? they are both seem to work correctly.

is it the same

No, it isn't.


char * test1() {
  char * returnValue = "test";
  return returnValue;
}  

The above code returns the fixed address to the constant literal "test" . This will be the same address each time the function is called.

It is not a dynamical allocation of memory .

Doing

printf("%d\n", test1() == test1());

will print

1

meaning "true", the two addresses returned are the same.

On " constness "

To better reflect the constness of the result of test1() it should better be defined as follows:

const char * test1() {
  const char * returnValue = "test";
  return returnValue;
}  

char * test2 {
  char * returnValue = strdup("test");
  return returnValue;
}

The above code returns the address to a freshly allocated area of memory having been copied "test" into. This will be a different *1 address each time the function is called.

*1: "different" at least, as long as the result of any previous call to test2() had not been free() ed already

This is a dynamical allocation of memory . It therefore requires a call to free() passing in the address returned by strdup() (which internally calls malloc() ) to deallocated the memory, if not needed any more.

Doing

printf("%d\n", test2() == test2()); /* leaks memory: 2 times 4+1 char */

will print

0

meaning "false", the two addresses returned are different.

For completeness: To avoid the leak as per the above snippet do

char * p, * q;
printf("%d\n", (p = test2()) == (q = test2()));
free(p);
free(q);

is it saft to use

Formally the code of both snippets is correct.

Which one to use and if the use if "safe" completely depends on the use case, on the the context.

char* test() {
    char* returnValue = "test";
    return returnValue;
}  

is it safe to use?

Yes, as long as you are not trying to modify the returnValue which is a string literal . The string literals have static storage duration, so they are alive throughout the lifetime of the program but attempt to modify the content of string literal is undefined behavior.

is it the same, as

char* test {
    char* returnValue=strdup("test");
    return returnValue;
}

Answer is - No

strdup()

Returns a pointer to a null-terminated byte string, which is a duplicate of the string pointed to by str1. The returned pointer must be passed to free to avoid a memory leak.

The strdup() uses malloc() to obtain memory for the new string, here the new string is "test" . It stays allocated until it is explicitly deallocated or until the program ends . So, it should be freed using free() once you are done with it. Also, you can modify the content of string returned by strdup() but make sure to not to access beyond the allocated memory chunk.

is it safe to use?

Yes, unless you try to change the string. There is no allocation in fact, so each time your function will return exactly the same pointer to the same location in memory.

is it the same, as

No, the strdup() makes an allocation and returns new allocated memory.

if yes, then should I free it later on?

It is no, but still you need to free the memory after strdup() later on.

they are both seem to work correctly

For printf() it is fine, unless you try to change those strings... You will not be able to change the char* returnValue = "test" string, but you will be able to change the string after strdup()

In both cases, "test" is allocated in the Stack as a read-only portion of memory ( const char ).

In the first block, you return a pointer to "test" . As said before, this will be always the same value across calls to the function. Due to its read-only property, trying to free or modify it, will raise an execution error ( munmap_chunk(): invalid pointer when trying to free, Segmentation fault when trying to modify).

In the second block, you return a pointer to a dynamically allocated portion of memory in the Heap . It's your responsibility to free this portion of memory using free() or equivalent. You are free to modify this variable, or even reallocate this portion of memory.

You can always do your own tests:

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

char* test1() {
    char* returnValue = "test";
    return returnValue;
}  
char* test2() {
    char* returnValue = strdup("test");
    return returnValue;
}

int main(void)
{
   char* vtest1 = test1();
   printf("%s => %p\n", vtest1, &vtest1);
   char* vtest2 = test2();
   printf("%s => %p\n", vtest2, &vtest2);

   printf("Freeing 2nd test...\n");
   free(vtest2);

   printf("Trying to modify 1st test...\n");
   vtest1[0] = 'p';
   printf("Freeing 1st test...\n");
   free(vtest1);

   return 0;
}

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