3

Possible Duplicate:
Undefined, unspecified and implementation-defined behavior

This should seg fault. Why doesn't it.

    #include <string.h>
    #include <stdio.h>

    char str1[] = "Sample string. Sample string. Sample string. Sample string. Sample string. ";
    char str2[2];

    int main ()
    {
      strcpy (str2,str1);
      printf("%s\n", str2);
      return 0;
    }

I am using gcc version 4.4.3 with the following command:

    gcc -std=c99 testString.c -o test

I also tried setting optimisation to o (-O0).

Community
  • 1
  • 1
siemanko
  • 1,389
  • 1
  • 13
  • 26

5 Answers5

8

This should seg fault

There's no reason it "should" segfault. The behaviour of the code is undefined. This does not mean it necessarily has to crash.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
4

A segmentation fault only occurs when you perform an access to memory the operating system knows you're not supposed to.

So, what's likely going on, is that the OS allocates memory in pages (which are typically around 4KiB). str2 is probably on the same page as str1, and you're not running off the end of the page, so the OS doesn't notice.

That's the thing about undefined behavior. Anything can happen. Right now, that program actually "works" on your machine. Tomorrow, str2 may be put at the end of a page, and then segfault. Or possibly, you'll overwrite something else in memory, and have completely unpredictable results.

edit: how to cause a segfault:

Two ways. One is still undefined behavior, the other is not.

int main() {
    *((volatile char *)0) = 42; /* undefined behavior, but normally segfaults */
}

Or to do it in a defined way:

#include <signal.h>

int main() {
    raise(SIGSEGV); /* segfault using defined behavior */
}

edit: third and fourth way to segfault

Here is a variation of the first method using strcpy:

#include <string.h>

const char src[] = "hello, world";
int main() {
    strcpy(0, src); /* undefined */
}

And this variant only crashes for me with -O0:

#include <string.h>

const char src[] = "hello, world";
int main() {
    char too_short[1];
    strcpy(too_short, src); /* smashes stack; undefined */
}
derobert
  • 49,731
  • 15
  • 94
  • 124
  • OK, but I really want to cause Segmentation fault. What can I do? I tried to increases string size to ~27K characters. I tried to surround it with declaration of other variables. Still no error. Any ideas? – siemanko Jan 27 '12 at 18:07
  • @nivwusquorum: I've edited with one way to be guaranteed a segfault, and one that is pretty sure. – derobert Jan 27 '12 at 18:39
  • Thanks very much! But what I actually meant is how to cause seqfault using strcpy. Can you come up with any example? Thanks! – siemanko Jan 27 '12 at 20:36
  • @nivwusquorum: OK, I've added ways to segfault with `strcpy`. – derobert Jan 27 '12 at 21:18
  • Thanks for anwser. But the problem is that last variant des not crash for me even if I add O0. And ideas how to make it more likely to crash? – siemanko Jan 27 '12 at 21:32
  • @nivwusquorum: Make the string longer, try `too_short+4` or some other number, try to 'hide' the undefined behavior from the compiler, etc. There isn't any way to guarantee it; its undefined. Its perfectly acceptable for the compiler to just omit the `strcpy` entirely. – derobert Jan 28 '12 at 05:27
2

Your program writes beyond the allocated bounds of the array, this results in Undefined Behavior.
The program is ill-formed and It might crash or may not.An explanation may or may not be possible.

It probably doesn't crash because it overwrites some memory beyond the array bounds which is not being used, bt it will once the rightful owner of that memory tries to access it.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
1

A seg-fault is NOT guaranteed behavior.

It is one possible (and sometimes likely) outcome of doing something bad.
Another possible outcome is that it works by pure luck.
A third possible outcome is nasal demons.

abelenky
  • 63,815
  • 23
  • 109
  • 159
0

if you really want to find out what this might be corrupting i would suggest you see what follows the over-written memory generate a linker map file that should give you a fair idea but then again this all depends on how things are layed out in memory, even can try running this with gdb to reason why it does or does not segfault, that being said, the granularity for built checks in access violations (HW assisted) cannot be finer than a page unless some software magic is thrown in (even with this page granularity access checking it may happen that the immediately next page does really point to something else for the program which you are executing and that it is a Writable page), someone who knows about valgrind can explain how it is able to detect such access violations (also libefence), most likely (i might be very wrong with this explanation, Correct me if i am wrong!) it uses some form of markers or comparisons for checking if out of bounds access has happened.