Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C memory management for variables

Tags:

c

pointers

I am new to C and I currently have some troubles. Please have a look at the following Code:

int main (int argc, char *argv[]) {
    int j = 2;
    int i = 100;    
    int *pi = &i;

    pi = &j;    //those 2 lines should do nothing, in my opinion
    pi = &i;    //

    pi[1] = -4;
    printf("i = %d, j = %d, *pi = %d\n", i, j, *pi);
    return EXIT_SUCCESS;
}

The code fails with a SegFault. Some investigation with gdb:

(gdb) print &j
$1 = (int *) 0x7fffffffde80
(gdb) print &i
$2 = (int *) 0x7fffffffde84

However, without the 2 lines, the code works fine, because i and j seem to swap places in the memory - but why??

(gdb) print &j
$1 = (int *) 0x7fffffffde84
(gdb) print &i
$2 = (int *) 0x7fffffffde80

I asked my teacher, but unfortunately she had no idea.

Thanks in advance!!

EDIT: by working fine, i mean the printf prints: i = 100, j = -4, *pi = 100 -- pi[1] points on j, seemingly

The question is, why do those 2 Lines change anything?

like image 439
user2343039 Avatar asked Mar 04 '15 09:03

user2343039


Video Answer


3 Answers

pi is a pointer and you are making it point to a integer later when you do

pi[1] = -4;

You are accessing the memory which is not under your control or the memory not allocated by you so it leads to undefined behavior hence the seg fault.

like image 104
Gopi Avatar answered Oct 12 '22 03:10

Gopi


Statement pi[1] = -4; invoke undefined behavior. Anything could happen. You may get either expected or unexpected results.

pi[1] = -4; is equivalent to *(pi+1) = -4;. Pointer one past the object i is allowed but dereferencing it will invoke undefined behavior.

C11:6.5.6 Additive operators:

7 For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.

8 If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.


The question is, why do those 2 Lines change anything?

The answer is, its because of undefined behavior.

like image 33
haccks Avatar answered Oct 12 '22 02:10

haccks


With my compiler it is as follows:

Of course pi[1] and &pi[1] is undefined behavior.

Setting a breakpoint on pi[1] = -4; and running the program:

This is the output with pi = &j; pi = &i;

Breakpoint 1, main (argc=1, argv=0x7fffffffe428) at tmp.c:12
12      pi[1] = -4;
(gdb) p &j
$1 = (int *) 0x7fffffffe334
(gdb) p &i
$2 = (int *) 0x7fffffffe330
(gdb) p &pi
$3 = (int **) 0x7fffffffe338
(gdb) p &pi[1]
$4 = (int *) 0x7fffffffe334
(gdb) c
Continuing.
i = 100, j = -4, *pi = 100
[Inferior 1 (process 2890) exited normally]
(gdb) 

&pi[1] points to j by chance

This is the output without pi = &j; pi = &i;

12      pi[1] = -4;
(gdb) p &j
$1 = (int *) 0x7fffffffe33c
(gdb) p &i
$2 = (int *) 0x7fffffffe32c
(gdb) p &pi
$3 = (int **) 0x7fffffffe330
(gdb) p &pi[1]
$4 = (int *) 0x7fffffffe330
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x000000000040056d in main (argc=1, argv=0x7fffffffe428) at tmp.c:13
13  printf("i = %d, j = %d, *pi = %d\n", i, j, *pi);
(gdb) p pi
$5 = (int *) 0x7ffffffffffc

With pi[1] = -4 (0xfffffffc) the pointer pi is modified pointing to a page where the process isn't allowed to read from, so the segmentation fault occurs.

You did not print pi, &pi and &pi[1] (which is UB), which would be of interest.

The answer to your question is:

The compiler is free to decide where and in which order it arranges the variables in the stack frame. As you changed the source code of the function the compiler can decide differently. Additionally, &pi[1] can point anywhere, as it is undefined behavior.

like image 23
4566976 Avatar answered Oct 12 '22 02:10

4566976