Sunday, 1 September 2013

Not receiving a seg fault when expected

Not receiving a seg fault when expected

I'm in the process of learning how to use pointers and structs in C.
Naturally, I'm trying to deliberately break my code to further understand
how the language works. Here is some test code that works as I expected it
to work:
#include <stdio.h>
#include <stdlib.h>
struct pair {
int x;
int y;
};
typedef struct pair pair;
void p_struct( pair ); //prototype
int main( int argc, char** argv ) {
pair *s_pair;
int size, i;
printf( "Enter the number of pair to make: " );
scanf( "%d", &size );
getchar();
printf( "\n" );
s_pair = (pair*)malloc( size * sizeof(pair) );
for( i = 0; i < size; i++ ) {
s_pair[i].x = i;
s_pair[i].y = i;
p_struct( s_pair[i] );
}
getchar();
return (EXIT_SUCCESS);
}
void p_struct( pair s_pair ) {
printf( "\n%d %d\n", s_pair.x, s_pair.y );
}
As previously stated, this code is functional as far as I can tell.
I then decided to modify a part of the code like so:
for( i = 0; i < size + 3; i++ ) {
s_pair[i].x = i;
s_pair[i].y = i;
p_struct( s_pair[i] );
}
This modification did not produce the seg fault error that I expected it
would. All of the "pairs" were printed despite me exceeding the buffer I
explicitly set when assigning a value to my variable size using the scanf
function.
As I understand pointers (correct me if I'm wrong), a contiguous block of
memory of size size*sizeof(pair) is reserved by the memory manager in the
heap when I called the malloc function for my pointer of type pair s_pair.
What I did was I exceeded the last assigned address of memory when I
modified my for loop to the condition i < size + 3.
If I'm understanding this correctly, did my pointer exceed its reserved
memory limit and just so happen to be in the clear because nothing
adjacent and to the right of it was occupied by other data? Is this normal
behaviour when overflowing a buffer?
To add, I did receive a seg fault when I tested with a for loop condition
of i < size + 15. The thing is, it still prints the output. As in, it
prints the pair "0 0" to pair "24 24" when size = 10 on the screen as per
the p_struct function I made. The program crashes by seg fault only after
it gets to one of those getchar()s at the bottom. How on earth could my
program assign values to pairs that exceed the buffer, print them on the
screen, and then all of a sudden decide to crash on seg fault when it gets
to getchar()? It seemed to have no issue with i < size + 3 (despite it
still being wrong).
For the record, I also tested this behaviour with a regular pointer array:
int size, i, *ptr;
scanf( "%d", &size );
ptr = (int*)malloc( size * sizeof(int) );
for( i = 0; i < size + 15; i++ )
ptr[i] = i;
This produces the exact same result as above. At i < size + 3 there
doesn't seem to be any issue with seg faults.
Finally, I tested with an array, too:
int i, array[10];
for( i = 0; i < 25; i++ )
array[i] = i;
For the condition i < 25, I get a seg fault without fail. When I change it
to i < 15, I receive no seg fault.
If I remember correctly, the only difference between an array of pointers
and an array is that the memory allocated to an array is located on the
stack as opposed to the heap (not sure about this). With that in mind, and
considering the fact that i < 15 when array[10] doesn't produce any seg
faults, why would i < 25 be an issue? Isn't the array at the top of the
stack during that for loop? Why would it care about 100 extra bytes when
it didn't care about 60 extra bytes? Why isn't the ceiling for that array
buffer all the way to the end of whatever arbitrary chunk of memory is
reserved for the whole stack?
Hopefully all of this made sense to whoever decides to read a slightly
inebriated man's ramblings.

No comments:

Post a Comment