1

So I think that what I got from this post is that it is UB or at least not a good idea to return pointers to locally defined variables, and in fact my compiler gives warning if I do this, however if I wrap the pointer in a struct then the warning no longer shows. Is it still UB or is there something different with structs that makes this OK. I'm using GCC 6.3.0 with -Wall.

Here is an example:

#include <stdio.h>

struct wrapper{
    int *ptr;
};

struct wrapper foo(){
    int a = 5;
    struct wrapper new_wrapper = {&a};
    return new_wrapper;
}

int main(){
    printf("%d", *foo().ptr); //prints 5, but will it theoretically always do so?
    return 0;
}
ripytide
  • 327
  • 2
  • 14
  • 2
    Once a variables life-time runs out, all pointers to it becomes invalid. Wrapping in structure, arrays or otherwise doesn't matter. – Some programmer dude Feb 27 '21 at 17:54
  • On my machine it prints 5 only when compiled without `-O2` – Arkadiusz Drabczyk Feb 27 '21 at 17:55
  • 1
    This is way more than just a bad idea. It is definitely undefined behavior, and not just in some abstract, theoretical sense: it will fail, badly, a large percentage of the time. – Steve Summit Feb 27 '21 at 18:08
  • 1
    What you need to think about here is not whether you get warning messages from the compiler or not, but *where the pointed-to memory is stored*. Non-static local variables all go away when the function returns, so pointers to any of them (no matter what type) become invalid. As ever, in C you always have to think pretty carefully about the allocation of the memory to which your pointer variables point. – Steve Summit Feb 27 '21 at 18:11
  • 1
    All you did by wrapping the pointer in a struct was camouflage your trickery from the compiler, so it was no longer able to detect the problem. But you did *not* do anything to change the essential allocation of `a`, or the inevitable eventual undefinedness of a pointer to it.. – Steve Summit Feb 27 '21 at 18:13
  • @ram914 Passing an input-only stream (like `stdin`) to `fflush` is explicitly mentioned in the C specification as leading to undefined behavior. It's really not something that should be recommended. – Some programmer dude Feb 27 '21 at 18:35

2 Answers2

2

Yes, it is. The local variable a lives only for the duration of foo.

Acorn
  • 24,970
  • 5
  • 40
  • 69
2

Returning a pointer is not a problem. The pointer and the object it points to are the problem. Using the pointer by any means is a problem, so wrapping it in a structure does not help.

When an object is “created” automatically inside a function, it is also “destroyed” when execution of the function ends. (In C, creating an object just means reserving memory for it, and destroying it means ending the reservation.)

Additionally, a pointer to memory that is no longer reserved is itself invalid. Although C implementations may implement pointers simply as memory addresses, some C implementations implement pointers in more complicated ways, and releasing the memory reservation may invalidate data needed to make the pointer work. So the C standard says that a pointer becomes invalid when the object it points to is released.

Because of that rule in the C standard, even implementations that implement pointers as memory addresses may treat pointers as invalid when the objects they point to are no longer reserved, with the result that optimization of the program by the compiler may cause any use of an invalid pointer to have unexpected effects.

ripytide
  • 327
  • 2
  • 14
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Here you say ```In C, creating an object just means reserving memory for it, and destroying it means ending the reservation.``` but then you say ```So the C standard says that a pointer becomes invalid when the object it points to is reserved``` Does this not contradict itslef? If its still reserved then is it not still valid? – ripytide Feb 27 '21 at 18:14
  • @Ripytide: Typo, fixed. – Eric Postpischil Feb 27 '21 at 18:23