0
#include <stdio.h>

int main()
{
    int *ptr;
    {
        int x = 2;
        ptr = &x;
    }

    printf("%x %d", ptr, *ptr);
    return 0;
}

Output: address of x, value of x.

Here, ptr should be a dangling pointer, right? Yet, it still stores the address of x. How is it still pointing the value of x, even after that block is deleted?

#include <stdio.h>

int * func (int n)
{
    int temp;
    int *ptr = &temp;
    temp = n * n;
    return ptr;
}

int main()
{
    int n = 4;
    int *p = func(4);
    printf("%x, %d", p, *p);
    return 0;
}

Output: address of temp, 16

In this program, the data variable temp and its pointer variable ptr is created in separate function. Why does it produce a correct result?

#include <stdio.h>

int * func (int n)
{
    int temp;
    int *ptr = &temp;
    temp = n * n;

    for (int i = 0; i < 10; i++)
        printf("%d ", *ptr);
    return ptr;
}
    
int main()
{
    int n = 4;
    int *p = func(4);
    printf("\n%x, %d", p, *p);
    for (int i = 0; i < 10; i++)
        printf("%d ", *ptr);
    *p = 12;
    printf("%d\n", *p);
    printf("%d\n", *p);
    return 0;
}

Output: 16 16 16 16 16 16 16 16 16 16
address of temp, 1
16 16 16 16 16 16 16 16 16 16
12
12

The above program is similar to the second one aside from the for loop. In the main() function, it gives the correct output every time. Even if I tried to change it to *p = 10, it would still give the correct output no matter how many times I print it.

But in the second program, it only gives the correct output once because of undefined behavior. It gives garbage values after the first printf.

But in third program, how does it still give the correct output every time?

My questions are:

  1. The pointer variable points to a local variable which goes out of scope, but still prints the correct output and is accessible through the pointer variable by changing it's value. Why is it?
  2. Like the temp created in increment(), ptr is also created locally. Why is it printing the values correctly all of the time without any warning or error? If the for loop is not there, it also gives an error after printing once. Why is that so?
    When I passed temp I got a warning and segmentation fault error. But why is ptr, a local variable, printing the values correctly?
  3. In the first program, after printing *ptr many times, it gives a correct output, and I was able to change *ptr = 1; after the first printf. Why can I access ptr even though the variable went out of scope?

Thank you everyone for answering. I underatand now from all your answers. Thank you very much.

INDHUJA G
  • 25
  • 4
  • 7
    you are introducing _undefined behavior_ – Daniel A. White Jul 03 '21 at 01:53
  • 1
    To clarify for @INDHUJA G as a new poster here and likely fairly new to C: undefined behaviour means your code _might_ work, but maybe not. If we did **know** it would be _defined_ behavior. It's best to avoid these kind of situations entirely. – Chris Jul 03 '21 at 02:20
  • @Chris and Daniel. Thank you for your answers. It should give undefined behavior only. But in 1st and 3rd program which I add now, looks like defined behavior. How is it possible? – INDHUJA G Jul 04 '21 at 03:58

3 Answers3

2

Both of your programs behaviour is undefined.

In first code, your program is accessing x, via its address, outside of block in which it was declared. x is a local(automatic) non-static variable and its lifetime is limited to its scope1) i.e. the block in which it has been declared. Any attempt to access it outside of its lifetime will result in undefined behaviour2). Same is the case with temp variable in second code.

An undefined behaviour includes it may execute incorrectly (either crashing or silently generating incorrect results), or it may fortuitously do exactly what the programmer intended.

Also, the correct format specifier for printing a pointer is %p.


1). From C11 Standard#6.2.1p4 [emphasis mine]

Every other identifier has scope determined by the placement of its declaration (in a declarator or type specifier). If the declarator or type specifier that declares the identifier appears outside of any block or list of parameters, the identifier has file scope, which terminates at the end of the translation unit. If the declarator or type specifier that declares the identifier appears inside a block or within the list of parameter declarations in a function definition, the identifier has block scope, which terminates at the end of the associated block. ......

2). From C11 Standard#6.2.4p2 [emphasis mine]

2 The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.34) If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.

H.S.
  • 11,654
  • 2
  • 15
  • 32
1

The 'x' in the first code, and the 'temp' in the second code is a local variables, and thus it is released from the stack when the variables are out of the defined block.

The 'ptr' and the 'p' are pointers to the address of these local variables, but the values stored in these pointers are not valid after the local variables are released from the stack.

After the local variable is released, whether the value remains in the memory or not, is a problem with the development tool and the environment. That is, the stack is released, then emptying the memory of the pointer that occupied the local variable, is being treated within the OS or compiler, and the point is that you can no longer use the value of that address valid.

When I reviewed VC ++ 2008, after the local variable was released, the pointer has no more valid value. It has random value.

secuman
  • 539
  • 4
  • 12
  • Thank you for your answer.Yes, it's undefined behavior. But in 1st and 2nd program , how it is like defined behavior. I have editedy question.Please could answer it? – INDHUJA G Jul 04 '21 at 04:01
1

I have disassembled your third program by IDA.
The func() function is compiled as a part of the main() function, not compiled as an independent function.

enter image description here So, the correct values are remained.
I guess this is the optimization result during compiling.

But, When I add one line to func(), the result of program is different.
enter image description here

In this case, the compiler recognized the 'func()' as a function.
The expected result is occurred and the program is crashed at '*p = 12'.

enter image description here

secuman
  • 539
  • 4
  • 12