Remapping String Literals

This is really a basic question, but I did not find a clear answer. I am trying to understand how string literals work in C

 #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char *str = "Hello World!"; str = "Reassign str."; char *str2 = "Something."; str = strdup(str2); free(str); exit(EXIT_SUCCESS); } 

When I do str = "Reassign str." or str = strdup(str2) into a string literal, what happens with the string Hello World ? Is this part of the executable, is it out of scope, is memory freed up after reassigning str ?

+7
c string pointers
source share
7 answers

String literals have a static storage duration. They are not destroyed and have the same address during program execution.

In these statements

  str = "Reassign str."; //... str = strdup(str2); 

The str pointer is simply reassigned to other addresses. In the first expression, it gets the address of the first character of the string literal "Reassign str". and in the second expression, it gets the address of the dynamically allocated memory for the character array, which contains a copy of the string literal pointed to by str2.

According to the C standard (6.4.5 string literals)

6 In phase 7 of the translation, bytes or a null code are added to each sequence of multibyte characters, which is obtained from a string literal or literals .78) A sequence of multibyte characters is then used to initialize an array of static storage duration , and the length is simply sufficient to contain the sequence. For character string literals, array elements are of type char and are individually initialized bytes of a multibyte character sequence.

AND (6.2.4 Duration of storage of objects)

3 Object ... has a static storage duration. Its lifetime is initialized to complete the program and its stored value only once, before the program starts

As for the string literals themselves, you cannot change them. Any attempt to modify a string literal results in undefined program behavior.

From C standard (6.4.5 String literals)

7 It is not known whether these arrays are different if their elements have corresponding values. If the program tries to change such an array, the behavior is undefined.

For example, you cannot write

  char *str = "Hello World!"; *str = 'h'; 
+4
source share

When you do

 char *str = "Hello World!"; 

the compiler allocates strlen(str) + 1 byte memory for this string literal. When the str pointer is reassigned, the memory allocated for the string literal "Hello World!" , is not destroyed / freed, but stored in its area.

+2
source share

Everything is fine in your code.

  char *str = "Hello World!"; 

OK, you declare a char * , pointing to the litteral line. To be true, you must write const char *str = because the litteral string is an immutable string ( str[4] = 'u'; will be incorrect)

  str = "Reassign str."; 

Ok, the str pointer now points to another litteral line. The same observation as above, it must be const.

  char *str2 = "Something."; 

Another story

  str = strdup(str2); 

Now str points to the string malloc'ed. For the first time, it is true that str will not be const. str[0] = 's'; will be right here.

  free(str); 

Ok, you free the line highlighted by strdup .

  exit(EXIT_SUCCESS); 

You perfectly return the setpoint (0) to the environment.

+2
source share

As if the answers weren't enough, but I think one aspect is still worth mentioning:

Yes, it’s correct that the string literal in your code has static storage, so it will be active during the whole execution of the program. In these conditions, nothing can happen to her (you cannot even change her). Technically, this means that the line is part of your program and is placed in a read-only data segment.

But in your case, the optimizing compiler will find that "Hello World!" never used, so it will disappear from your compiled program. This is necessary for the optimizer, since it does not change the observed behavior of your program.

 > gcc -ostrlit strlit.c > strings strlit | grep Hello Hello World! > gcc -O3 -ostrlit strlit.c > strings strlit | grep Hello > 
+2
source share

Typically, static rows are in the static data section. In this case, since the program does nothing, I am not sure; all your static lines can be optimized.

In a real program where you really use these static lines, they will have a fixed address.

In no case str = strdup(str2); does not free memory. In memory, C is never freed by itself.

+1
source share

Let's break it down:

 char *str = "Hello World!"; 

declares a pointer to char called str

 char *str 

and also declares a string literal

  "Hello World!"; 

and also sets str to point to the first character of the literal.

A literal has a static storage duration - it is compiled into your executable file, it always exists and cannot be moved or changed.

A pointer is just a pointer, and you can point it to other things whenever you want.

+1
source share

When declaring a string literal such as:

 char *str = "Hello World!"; 

The string "Hello World!" stored in a read-only memory section. So, if you are one of them:

 str[1] = 'i'; strcpy(str, "Goodbye!"); 

You will most likely be the main dump. If, on the other hand, you do this:

 str = malloc(10); strcpy(str, "Goodbye!"); 

You will be fine, although you will lose the pointer that you had with the original string.

0
source share

All Articles