String Literals In Go, strings exist within either back quotes ` (sometimes referred to as back ticks) or double quotes " . Depending on which quotes you use, the string will have different characteristics. Using back quotes, as in ` ```bar``` ` , will create a raw string literal.
The characters of a literal string are stored in order at contiguous memory locations. An escape sequence (such as \\ or \") within a string literal counts as a single character. A null character (represented by the \0 escape sequence) is automatically appended to, and marks the end of, each string literal.
The data of a running process is organized into five segments: The code segment contains the program text; that is, the machine language instructions that make up the program. The static segment contains immutable values, like string literals.
When strings are declared as character arrays, they are stored like other types of arrays in C. For example, if str[] is an auto variable then string is stored in stack segment, if it's a global or static variable then stored in data segment, etc.
A common technique is for string literals to be put in "read-only-data" section which gets mapped into the process space as read-only (which is why you can't change it).
It does vary by platform. For example, simpler chip architectures may not support read-only memory segments so the data segment will be writable.
Rather than try to figure out a trick to make string literals changeable (it will be highly dependent on your platform and could change over time), just use arrays:
char foo[] = "...";
The compiler will arrange for the array to get initialized from the literal and you can modify the array.
Why should I not try to alter it?
Because it is undefined behavior. Quote from C99 N1256 draft 6.7.8/32 "Initialization":
EXAMPLE 8: The declaration
char s[] = "abc", t[3] = "abc";
defines "plain" char array objects
s
andt
whose elements are initialized with character string literals.This declaration is identical to
char s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' };
The contents of the arrays are modifiable. On the other hand, the declaration
char *p = "abc";
defines
p
with type "pointer to char" and initializes it to point to an object with type "array of const char" with length 4 whose elements are initialized with a character string literal. If an attempt is made to usep
to modify the contents of the array, the behavior is undefined.
Where do they go?
GCC 4.8 x86-64 ELF Ubuntu 14.04:
char s[]
: stackchar *s
:
.rodata
section of the object file.text
section of the object file gets dumped, which has Read and Exec permissions, but not WriteProgram:
#include <stdio.h>
int main() {
char *s = "abc";
printf("%s\n", s);
return 0;
}
Compile and decompile:
gcc -ggdb -std=c99 -c main.c
objdump -Sr main.o
Output contains:
char *s = "abc";
8: 48 c7 45 f8 00 00 00 movq $0x0,-0x8(%rbp)
f: 00
c: R_X86_64_32S .rodata
So the string is stored in the .rodata
section.
Then:
readelf -l a.out
Contains (simplified):
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x0000000000000704 0x0000000000000704 R E 200000
Section to Segment mapping:
Segment Sections...
02 .text .rodata
This means that the default linker script dumps both .text
and .rodata
into a segment that can be executed but not modified (Flags = R E
). Attempting to modify such a segment leads to a segfault in Linux.
If we do the same for char[]
:
char s[] = "abc";
we obtain:
17: c7 45 f0 61 62 63 00 movl $0x636261,-0x10(%rbp)
so it gets stored in the stack (relative to %rbp
), and we can of course modify it.
There is no one answer to this. The C and C++ standards just say that string literals have static storage duration, any attempt at modifying them gives undefined behavior, and multiple string literals with the same contents may or may not share the same storage.
Depending on the system you're writing for, and the capabilities of the executable file format it uses, they may be stored along with the program code in the text segment, or they may have a separate segment for initialized data.
Determining the details will vary depending on the platform as well -- most probably include tools that can tell you where it's putting it. Some will even give you control over details like that, if you want it (e.g. gnu ld allows you to supply a script to tell it all about how to group data, code, etc.)
FYI, just backing up the other answers:
The standard: ISO/IEC 14882:2003 says:
2.13. String literals
[...]An ordinary string literal has type “array of
n const char
” and static storage duration (3.7)Whether all string literals are distinct (that is, are stored in nonoverlapping objects) is implementation- defined. The effect of attempting to modify a string literal is undefined.
gcc makes a .rodata
section that gets mapped "somewhere" in address space and is marked read only,
Visual C++ (cl.exe
) makes a .rdata
section for the same purpose.
You can look at the output from dumpbin
or objdump
(on Linux) to see the sections of your executable.
E.g.
>dumpbin vec1.exe
Microsoft (R) COFF/PE Dumper Version 8.00.50727.762
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file vec1.exe
File Type: EXECUTABLE IMAGE
Summary
4000 .data
5000 .rdata <-- here are strings and other read-only stuff.
14000 .text
It depends on the format of your executable. One way to think about it is that if you were assembly programming, you might put string literals in the data segment of your assembly program. Your C compiler does something like that, but it all depends on what system you're binary is being compiled for.
String literals are frequently allocated to the read-only memory, making them immutable. However, in some compilers modification is possible by a "smart trick"..And the smart trick is by "using character pointer pointing to memory"..remember some compilers, may not allow this..Here is demo
char *tabHeader = "Sound";
*tabHeader = 'L';
printf("%s\n",tabHeader); // Displays "Lound"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With