I have to show an error when I access an item outside of an array (without creating my own function for it). So I just thought it was necessary to access the value out of the array to trigger a segfault but this code does not crash at all:
int main(){
int tab[4];
printf("%d", tab[7]);
}
Why I can't get an error when I'm doing this?
When you invoke undefined behavior, anything can happen. You program may crash, it may display strange results, or it may appear to work properly.
Also, making a seemingly unrelated change such as adding an unused local variable or a simple call to printf
can change the way in which undefined behavior manifests itself.
When I ran this program, it completed and printed 63. If I changed the referenced index from 7 to 7000, I get a segfault.
In short, just because the program can crash doesn't mean it will.
Because the behavior when you do things not allowed by the spec is "undefined". And because there are no bounds checks required in C. You got "lucky".
int tab[4];
says to allocate memory for 4 integers on the stack. tab
is just a number of a memory address. It doesn't know anything about what it's pointing at or how much space as been allocated.
printf("%d", tab[7]);
says to print out the 8th element of tab
. So the compiler does...
tab
is set to 1000 (for example) meaning memory address 1000.tab
represents a list of int
, so each element will be sizeof(int)
, probably 4 or 8 bytes. Let's say 8.tab[7]
means to start reading at memory position (7 * 8) + 1000 = 1056 and for 8 more bytes. So it reads 1056 to 1063.That's it. No bounds checks by the program itself. The hardware or OS might do a bounds check to prevent one process from reading arbitrary memory, have a look into protected memory, but nothing required by C.
So tab[7]
faithfully reproduces whatever garbage is in 1056 to 1063.
You can write a little program to see this.
int main(){
int tab[4];
printf("sizeof(int): %zu\n", sizeof(int));
printf("tab: %d\n", tab);
printf("&tab[7]: %d\n", &tab[7]);
/* Note: tab must be cast to an integer else C will do pointer
math on it. `7 + tab` gives the same result. */
printf("(7 * sizeof(int)) + (int)tab: %d\n", (7 * sizeof(int)) + (int)tab);
printf("7 + tab: %d\n", 7 + tab);
}
The exact results will vary, but you'll see that &tab[7]
is just some math done on tab
to figure out what memory address to examine.
$ ./test
sizeof(int): 4
tab: 1595446448
&tab[7]: 1595446476
(7 * sizeof(int)) + (int)tab: 1595446476
7 + tab: 1595446476
1595446476 - 1595446448 is 28. 7 * 4 is 28.
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