1

I was trying to access a variable from the previous stack and it gave me the following error in Linux:

.... terminated by signal SIGSEGV (Address boundary error

However in CS61C lecture from 2014, the output was coming as:

3
Something Random

enter image description here

  1. How did it even work in that machine vs my Linux?
  2. Why did it print 3 the first time but not the second time? If printf didn't use that slot for something else, that behavior should have happened the second time as well no?

Below is the code:

#include<stdio.h>

int *ptr() {
    int y;
    y = 3;
    return &y;
}

main() {
    int *stackAddr, content;
    stackAddr = ptr();
    content = *stackAddr;
    printf("%d", content);
    content = *stackAddr;
    printf("%d", content);
}
Nishant
  • 17,152
  • 14
  • 56
  • 80
  • 5
    Thats just plain old undefined behavior, there is no "why". – tkausl Jan 23 '19 at 10:35
  • Is that a coincidence that 3 came up the very first time? – Nishant Jan 23 '19 at 10:36
  • Yes, it could've been 7 or 42 or "format c" instead. – tkausl Jan 23 '19 at 10:38
  • 2
    **It is UB: don't do it!** The first time you use `*stackAddr` it has stuff from `ptr()`; the second time it has stuff from `printf()`. – pmg Jan 23 '19 at 10:42
  • 1
    The behaviour of that code is undefined, which means the C standard doesn't specify any constraints on what happens. What happens CAN BE (but is not required to be) different for different compilers, different for the same compiler with different settings (e.g. optimisation), or even be different for different phases of the moon. – Peter Jan 23 '19 at 11:13
  • 1
    Please read the top-voted answer of the linked duplicate. It answers everything asked here. – Lundin Jan 23 '19 at 12:45

2 Answers2

2

The lecture notes are more about a study of the behaviour of a particular compiler rather than anything else: The assertion in your picture that "Pointers in C allow access to deallocated memory" is not true from a language perspective; the behaviour is merely undefined by the C standard.

Your best bet here therefore is to inspect the generated assembly; this is unanswerable at the language level as the language does not define the behaviour.

Bathsheba
  • 220,365
  • 33
  • 331
  • 451
1

Your assumption is not exactly true:

If printf didn't use that slot for something else, that behavior should have happened the second time as well no?

No.

For the first call the illegal memory access is done before calling printf as the parameter must be evaluated before you can call the function. For the second call the expression is evaluated again and anything could have happened in the meantime.

That's what happens if you invoke UB.

Gerhardh
  • 7,440
  • 2
  • 11
  • 29
  • Thanks. I was thinking that the de-referencing is happening *inside* the function i.e we are *passing* the pointer inside. Anyway, other answers are super useful as well. – Nishant Jan 23 '19 at 12:30
  • The lecture also said why he was doing it in two steps, `content` and `*stackAddr` instead of directly using `*stackAddr` i.e `printf("%d", *stackAddr);` which might lead to some confusion about the order of evaluation. Looking back, it all makes sense now. – Nishant Jan 23 '19 at 17:42
  • @Nishant that doesn't make any difference. All parameters must be known before they can ne passed to a function. Once the called function ist entered, it's too late. – Gerhardh Jan 23 '19 at 17:45
  • Yeah @Gerhardh, but at-least in that case it is implicit. The order in the syntax and evaluation are different. The lecturer made it explicit by avoiding all these confusions, but even then I managed to get confused xD. – Nishant Jan 24 '19 at 03:50