Duck Dodgers
Duck Dodgers

Reputation: 3461

Do I misunderstand this example about scope of string literals?

I was reading up on common C pitfalls and came up to this article on some famous Uni website. (It is the 2nd link that comes up on google).

The last example on that page is,

// Memory allocation on the stack
void b(char **p) {
    char * str="print this string";
    *p = str;
}

int main(void) {
    char * s;
    b(&s);
    s[0]='j'; //crash, since the memory for str is allocated on the stack, 
              //and the call to b has already returned, the memory pointed to by str 
              //is no longer valid.
    return 0;
}

That explanation in the comment got me thinking then, that, isn't the memory for string literals not static?

Isn't the actual error there then that you are not supposed to modify string literals, because it is undefined behavior? Or are the comments there correct and my understanding of that example is wrong?

Upon searching further, I saw this question: referencing a char that went out of scope and I understood from that question that, the following is valid code.

#include <malloc.h>
char* a = NULL;
{
    char* b = "stackoverflow";
    a = b;
}

int main() {
    puts(a);
}

Also this question agrees with the other stackoverflow question and my thinking, but opposes the comment from that website's code.

To test it, I tried the following,

#include <stdio.h>
#include <malloc.h>

void b(char **p)
{
    char * str = "print this string";
    *p = str;
}

int main(void)
{
    char * s;
    b(&s);
    // s[0]='j'; //crash, since the memory for str is allocated on the stack,
                //and the call to b has already returned, the memory pointed to by str is no longer valid.
    printf("%s \n", s);
    return 0;
}

which as expected does not give a segmentation fault.

Upvotes: 1

Views: 94

Answers (3)

Jean-Baptiste Yun&#232;s
Jean-Baptiste Yun&#232;s

Reputation: 36391

Standard says (emphasize is mine):

6.4.5 String literals

  1. [...] The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence. [...]

  2. [...] If the program attempts to modify such an array, the behavior is undefined. [...]

Upvotes: 3

SergeyA
SergeyA

Reputation: 62563

No, you misunderstand the reason for crash. String literals have static duration, meaning that they exist for the lifetime of the program. Since your pointer points to the literal, you can use it anytime.

The reason for the crash is the fact that string literals are read-only. In fact char* x = "" is an error in C++, as it should be const char* x = "". They are read-only from language perspective, and any attempt to modify them would lead to undefined behavior.

In practical terms, they are often put in the read-only segment, so any attempt at modification triggers a GPF - general protection fault. Usual response to GPF is a program termination - and this is what you are witnessing with your application.

Upvotes: 2

izac89
izac89

Reputation: 3930

String literals are placed in general in rodata section (read-only) within the ELF file, and under Linux\Windows\Mac-OS they will end up in a memory region which will generate a fault when written to (configured so using MMU or MPU by the OS upon loading)

Upvotes: 1

Related Questions