Is it safe to return local struct variable's member variable?

Viewed 102
struct SGetWindow
{
    HWND__* pWindow;
};
SGetWindow getWindow;
EnumWindows(GetWindowProc, reinterpret_cast<LParam>(&getWindow));
return getWindow.pWindow;

Using SGetWindow struct as LParam, HWND__* pWindow is successfully updated.

I wonder if this usage of returning member variable of local struct variable is safe.

return getwindow.pWindow;

Is it safe? or cause undefined behavior?

EDIT: I added an image for understanding.

Q1

I understood that the value of pointer (0x00000000000506D8 or 0x00000000000606D8) 1) is valid after function termination, 2) will be copied. But I don't think that guarantees safeness because the matter it seems is 'access (local struct member variable that no longer exist), and return its value'.

EDIT2:

I was thinking wrong and I was so dumb.

According to what I was thinking, even returning local int variable would lead to undefined behavior. For example,

int func()
{
int a = 10;
return a;
}

Local variable 'a' no longer valid when function exits. Thus, return value is undefined behavior.

However, this isn't. Because it is 'return by value' type. The value is copied (somewhere), and the copy process is before local variable goes out of scope.

Operation sequence would be something like

  1. Allocate n bytes for local variable and set its value as 10.

2. Copy the local variable's value to 'somewhere'.

  1. Function exits and local variables become invalid (reverting EBP).

"Another advantage of return by value is that you can return variables (or expressions) that involve local variables declared within the function without having to worry about scoping issues. Because the variables are evaluated before the function returns, and a copy of the value is returned to the caller, there are no problems when the function’s variable goes out of scope at the end of the function."

https://www.learncpp.com/cpp-tutorial/74a-returning-values-by-value-reference-and-address/

"The copy-initialization of the result of the function call is sequenced-before the destruction of all temporaries at the end of expression, which, in turn, is sequenced-before the destruction of local variables of the block enclosing the return statement."

https://en.cppreference.com/w/cpp/language/return

EBP revert

https://en.wikibooks.org/wiki/X86_Disassembly/Functions_and_Stack_Frames

Shame on me! Thank you for kind answers by the way.

2 Answers

This is safe.

You're returning the value of getWindow.pWindow, which happens to be a pointer. This pointer was populated by a call to EnumWindows, not by assigning the address of a local variable.

It's fine, assuming the address in pWindow will continue to exist after the function returns. You can't return a pointer to pWindow (&getWindow.pWindow), but you can return its value (getWindow.pWindow), as long as the value remains valid. pWindow is destroyed when the function returns but that's okay since its value is being copied. If pWindow points to a local variable then you can't do it, but if it points elsewhere then it's safe.

Related