1

I have the following struct:

struct foo{
    int a[4];
    int b[4];
}

I have the following function:

foo get_foo()
{
    foo ret_val;
    <..some assignments here..>
    return ret_val;
}

Now, my main code:

void* process_a()
{
    int* pa = get_foo().a;
    <..do smth with "pa"..>
     return pa;
 }

It appears that the code is running fine, but it is completely unknown what happens with complete structure, since I have access only to subpart of it. And, the questions:

  • is it fine to assign to a pointer only a part of the structure created on stack?
  • where is the foo structure? on stack? or heap?
  • Is compiler smart enough to allocate only int[4] (which is quite unlikely) or it will alloc the complete foo?
  • what is the time to live for my pa? Can I reliably use that pointer outside the process_a() function?

Thanks! Igor.

trincot
  • 317,000
  • 35
  • 244
  • 286
Igor_K
  • 25
  • 6
  • possible duplicate of [Can a local variable's memory be accessed outside its scope?](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – Baum mit Augen May 29 '15 at 12:43
  • 1
    You cannot even use `pa` inside `process_a` since it does not point anywhere meaningful. – Baum mit Augen May 29 '15 at 12:44
  • 1
    You can't use `pa` even *inside* the `process_a` function, because once the expression `pa = get_foo().a` is done the returned structure is destructed leaving you with a stray pointer. If you need `a` the you should *copy* it. And remember: It will be so much easier to handle things like this if you just use the proper C++ classes, like [`std::array`](http://en.cppreference.com/w/cpp/container/array) in your case. – Some programmer dude May 29 '15 at 12:47

2 Answers2

0
  • Yes, it's fine to assign a pointer to an inner field of a structure.
  • foo is on stack
  • like you said - it's quite unlikely
  • lifetime of pa is just like of any local variable - till the end of func. You can't use it beyond the func scope. However, you have a different problem here - the return value of get_foo is temporary and once you're beyond the scope of assignment to pa, it can get deallocated, thus any usage of data pointed by pa after that will result in undefined behavior.
SomeWittyUsername
  • 18,025
  • 3
  • 42
  • 85
  • 2
    The first point is fine *if* the structure was on the stack, but it isn't. The structure returned by `get_foo` isn't stored anywhere and so it's temporary and will cease to exist at the end of the expression. – Some programmer dude May 29 '15 at 12:49
  • @JoachimPileborg Well, the return value has to be stored somewhere at least till the end of expression. To the best of my knowledge the standard location for return values is stack. In fact, see here: http://stackoverflow.com/questions/9109831/where-are-temporary-object-stored – SomeWittyUsername May 29 '15 at 14:28
  • Maybe the compiler will store it on the stack, maybe it will optimize it some way or another, there's no way of knowing. What we *do* know is that the **temporary** object *will* be destructed and no longer valid after the assignment. Storing any kind of pointer to destructed objects or their members is a recipe for disaster and the way to undefined behavior. – Some programmer dude May 29 '15 at 14:44
  • @JoachimPileborg No dispute about that and I mentioned it explicitly in my 4th bullet. But my first bullet deals with the validity of assigning a pointer to an inner field of the returned value. The assigning itself is perfectly valid. It will become a dangling pointer immediately after that, but it's a completely different issue – SomeWittyUsername May 29 '15 at 14:47
0
  • Yes, but it is only valid during the structure's lifetime.
  • The structure returned from the function is a temporary object, and it gets destroyed immediately.
    There will be some space, probably "on the stack", for the function to return its result into.
    Once the right hand side of the assignment has executed, the structure is not stored anywhere, because it doesn't exist.
  • It will almost certainly allocate space for an entire structure.
  • The lifetime of pa is the body of process_a, but the lifetime of *pa has expired as explained above.
    Because of this, you can't use the value of pa for anything (except copying it) even inside process_a.

Your code appears to be running fine because "appears to be running fine" is a valid form of undefined behaviour, like anything and everything else.

molbdnilo
  • 64,751
  • 3
  • 43
  • 82