denc4 said:
i think you can't modify a literal string in one go, but ofcourse you can modify it in parts:
Your code snippet works. However, in your code snippet, you aren't modifying the string literal; you're modifying an
array initialized to the value of the string literal. That array is non-[tt]const[/tt], and is located on the stack.
If you try to modify an actual string literal, you're likely to get a memory error. For example:
Code:
[COLOR=blue]$ cat >lit.c[/color]
int main ()
{
char *literal = "hello!";
literal[0] = 'H';
return 0;
}
[COLOR=blue]$ gcc -Wall -s -o lit lit.c[/color]
[COLOR=blue]$ ./lit[/color]
[highlight]Segmentation fault[/highlight]
That's because my compiler/linker built an object file that stored that string literal in a section called [tt].rodata[/tt], which stands for "read-only data":
Code:
[COLOR=blue]$ objdump -s -j .rodata lit[/color]
lit: file format elf32-i386
Contents of section .rodata:
8048490 03000000 01000200 [highlight]68656c6c 6f2100[/highlight] ........[highlight]hello!.[/highlight]
On further investigation, we can see that the section [tt].rodata[/tt] is indeed marked with a read-only flag in the object file:
Code:
[COLOR=blue]$ objdump -h lit |grep -A1 '\.rodata'[/color]
13 .rodata 0000000f 08048490 08048490 00000490 2**2
CONTENTS, ALLOC, LOAD, [highlight]READONLY[/highlight], DATA
So when my operating system kernel (Linux) loads that executable object file into memory, it takes the hint and loads the [tt].rodata[/tt] section into an area of memory for which it has disabled writing, enabling it to enforce that constraint. When the process attempts to modify data in that area of memory, the kernel kills it for accessing memory in a way it wasn't supposed to. That was the "Segmentation Fault" above.
denc4 said:
can you tell me what the difference is between the "initialized static data section" as you mentioned earlier, and the heap?
The "initialized static data section" is a section for static data that's initialized
Taken in pieces:
[ul]
[li]
data
This one's easy. It's not code; it's data.
[/li]
[li]
static
Here, "static" is almost a synonym for "global." It just means the data is going to
stay around for the whole process. It also implies that you know what the data is and how much of it there will be when you write the program.
[/li]
[li]
initialized
This just means you specified an initial value for the data.[/li]
[/ul]
I probably also should have used the word "constant" in my description; that would mean the same as "read-only."
When your compiler/linker builds your executable, it puts static data into sections. That way, the OS kernel can load that data up when the process starts, and have it stick around for the duration of the process.
The "initialized" part basically just means the object file has to contain the initial values for the data. It can save quite a bit of space for static data that doesn't need to be initialized. (However, when dealing with a constant value such as our string literal, you have to initialize it because your program doesn't get to change it (as we've seen)).
The heap, on the other hand, is a pool of memory from which your program can, at runtime, request chunks using funnctions like [tt]malloc[/tt]; when it's done, it can give them back with [tt]free[/tt].
When you don't know exactly how much data you're going to need, you store it in heap memory instead of static memory. That way, you can allocate as much as you need and no less (and usually not much more).
You also have control over how long you have heap memory allocated. It doesn't stick around for the entire lifetime of the process like static data does (unless you want it to).
Finally, since your program determines everything about how (and if) heap memory gets used at
runtime, you don't store heap data in the object file like you do with static data.
*Whew,* you asked a mouthful. ;-)