0

Possible Duplicate:
Why don’t I get a segmentation fault when I write beyond the end of an array?

I was just playing with pointers when I realized that something strange was happening. I am aware that whenever we want to copy a string src to another string dst, using strcpy, for instance, we should allocate the required space for src.

    char *dst,*src = "asdlskafksdhfklshfkshdkfhksdhfçsahdflçsdhfçklshadfç";

    dst = (char*)malloc(1); //only one char allocated
    strcpy(dst,src);

    printf("dst=%s.\n",dst);

This code should not execute. However that is not happening. The code executes, copies successfully the src into dst and prints dst like a charm. Could someone of you, explain me why is this happening, please?

Community
  • 1
  • 1
Leaurus
  • 376
  • 3
  • 13
  • 9
    It's undefined behaviour. It may manifest as doing what the programmer intended. Or not. – Daniel Fischer Oct 11 '12 at 22:12
  • @DanielFischer: isn't it a little bit disappointing that the scientifically strict guys who invented C left so many details out from the C specification. There are so many "undefined behavior features" in C! – Razvan Oct 11 '12 at 22:15
  • @Razvan: this is so much intentional. – akappa Oct 11 '12 at 22:17
  • @Razvan - you would prefer that it was defined to do something specific like flash the warning light on the PDP11 it was first implemented on? On some machines that C runs on programs and data may not even be able to see the same memory – Martin Beckett Oct 11 '12 at 22:18
  • Thanks. I was not aware of this concept. – Leaurus Oct 11 '12 at 22:20

4 Answers4

2

Part of the performance of C is that it does not have much in the way of built in error checking. All strcpy knows is that it was passed a pointer of the correct type, it doesn't know how much allocated memory it was pointing at. The resulting machine code simply reads from the src pointer up to the first null byte and then pastes it into the dst pointer. If it doesn't overwrite somebody else's memory, there is no error.

What is "someone else's memory"? Generally a process is allocated memory in pages. When you malloc one byte, the process is given a whole page of memory, probably a few kilobytes, to slice and dice as it needs. Segmentation faults occur when your process tries to write outside its allocated pages, and for other reasons. The error is typically generated by the operating system and/or hardware which is doing the memory management. Since src is only a few dozen bytes it is unlikely to walk outside the process' page. If you make src a longer string, you'll probably get the segfault you're expecting.

There are various malloc wrapper libraries used for debugging which, through various tricks, make C check for memory mistakes. Valgrind and Electric Fence being some of the most famous.

PS I'm a little hazy on exactly how this stuff works, but its more satisfying than "it's undefined behavior". Please feel free to edit where my explanation is lacking.

Schwern
  • 153,029
  • 25
  • 195
  • 336
  • Thank you! I guess my concept of 'somebody else's memory' was incorrect or it was very obscure. I ran Valgrind and it identified immediately the problem. ;) – Leaurus Oct 11 '12 at 22:37
  • 1
    I might add that `malloc` is part of a user space library that manages pages allocated by the *kernel* (generally). Otherwise you might run into some confusion with "when I call `free()` does it also deallocate the entire page?" – rliu Oct 11 '12 at 22:38
  • But imagine the whole page or several pages get empty with the call free(). Then they are deallocated, right? – Leaurus Oct 11 '12 at 22:43
  • 1
    Depends on your libc (ie, it's an implementation detail). For glibc on *NIX, it's only released when the process exits, but of course that physical memory can be reused anyway. – Useless Oct 11 '12 at 22:47
2

Your string is allocated on the heap. The heap does not have a size of only 1 byte, rather around 4kb physical RAM (default windows console application size).

You will only get segmentation fault when trying to write to a memory area outside the heap. You are however, likely to destroy the memory for other parts of an application. But as your program is so small, and terminates just after writing beyond the allocated memory, you are unlikely to see any errors

Storstamp
  • 425
  • 2
  • 8
1

In release build *dst points at some memory in your process's address space - you write to that, if it happens to be occupied by something useful like your app it will crash.

In debug build it's likely that your compiler sets *dst to 0 or some recognisable value like 0xDEADBEEF so you can spot this.

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
1

If you write outside allocated memory the results are undefined. If you are lucky you get a segfault. If you are unlucky, other variables get overwritten. Bottom line: anything goes!

Klas Lindbäck
  • 33,105
  • 5
  • 57
  • 82