c++constantsconstexprlifetimenull-terminated

Does a const char* literal string persistently exist as long as the process alive?


I have functions like the following:

const char* get_message() {
    return "This is a constant message, will NOT change forever!";
};

const char* get_message2() {
    return "message2";
};

And I'm planning to use them everywhere my app, even though in different threads.

I'm wondering about the life time of these strings, i.e. whether it's safe to use these const char* string out of the function get_message.

I guess that a hard coded const char* string will be compiled into the codes segment of a app instead of the data segments, so maybe it is safely to use them as above?


Solution

  • Short answer is string literal "message2" will exist in memory as long as process, but in .rodata section (assuming we talk about ELF file).

    We return pointer to string constant, but as we will latter see, there is not separate memory defined anywhere which stores this const char * pointer and there is no need to, as address of string is calculated in code and returned using register $rax every time function is called.

    But lets take a look in the code what happens with gdb

    enter image description here

    We put breakpoint in our function returning a pointer to constant string, and we see assembly code and process map:

    enter image description here

    Code gets this string in following instruction:

    0x000055555555514a <+8>:    lea    0xeb3(%rip),%rax        # 0x555555556004
    

    What this instruction does it calculates address of "message2". We see here what PIC (position independent code) means.

    Address of "message2" string is not hardcoded as absolute, but is calculated as relative, as hardcoded offset 0xeb3 of next instruction address (0x555555555151 + 0xeb3) and put in register rax.

    Purpose of relative addressing (current address +/- offset) means process will always get the right address of "message2", no matter where in memory it is loaded.

    So here we see that const char * that you asked actually doesn't exist in memory, because address is calculated "on the fly" and returned using $rax:

    We have address in $rax:

    (gdb) i r $rax
    rax   0x555555556004      93824992239620
    

    And it holds address of "message2":

    (gdb) x/s 0x555555556004
    0x555555556004: "message2"
    

    Now lets see where address 0x555555556004 in process address map is:

    0x555555556000     0x555555557000     0x1000     0x2000  r--p   /home/drazen/proba/main
    

    So this section is not executable and not writable, just readable and private (r--p) which makes sense as this is not shared library.

    When we check with readelf it shows that it is in the .rodata section of ELF file:

    drazen@HP-ProBook-640G1:~/proba$ readelf  -x .rodata main
    
    Hex dump of section '.rodata':
    0x00002000 01000200 6d657373 61676532 00       ....message2.
    

    So answer is that this string will not be hardcoded in code segment .text of the ELF file but read only data segment .rodata, but yes it will exist as long process exists in memory.

    And just to add small detail, this constant string will be returned to main() function by reference of course (address), but not on the stack but in register rax:

    (gdb) i r
    rax   0x555555556004      93824992239620
    rbx   0x0 
    

    Hope it helps!