Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'Lucky' valid pointer data to returned local map data?

Tags:

c++

In my C++ program I have a function that returns a map containing elements that each can have a pointer to another element in the map. I set these pointers before returning the map at the end of the function. Example code:

#include <iostream>
#include <map>
#include <string>

class TestObject{
public:
    TestObject(std::string message) : message(message), other(nullptr){}

    TestObject* other;
    std::string message;
};

std::map<std::string, TestObject> mapReturningFunction(){
    std::map<std::string, TestObject> returnMap;

    TestObject firstObject("I'm the first message!");

    returnMap.insert(std::make_pair("first", firstObject));

    TestObject secondObject("I'm the second message!");
    returnMap.insert(std::make_pair("second", secondObject));

    TestObject* secondObjectPointer = &(returnMap.at("second"));
    returnMap.at("first").other = secondObjectPointer;

    return returnMap;
}

int main(){
    std::map<std::string, TestObject> returnedMap = mapReturningFunction();

    std::cout << returnedMap.at("first").other->message << std::endl; // Gives a valid message every time

    std::cin.get();

    return 0;
}

At the call-site of the function, the pointer other is still valid, even though I suspected it would become invalid because the map inside the function of which the 'pointed-to object' is an element of goes out of scope.

Is this basically the same as mentioned in Can a local variable's memory be accessed outside its scope? ? I'm basically 'lucky' the pointer is still pointing to valid data? Or is something different going on?

I really do think it is a 'lucky' hit every time, but some confirmation would be very nice.

like image 988
Soulrot Avatar asked Aug 06 '14 17:08

Soulrot


2 Answers

Yes, you are "lucky" (not that much, your program will crash or do bad things in a way or another sooner or later).


Explanation:

returnMap is allocated on the stack: it will be destroyed when mapReturningFunction returns.

You take the address of an object inside the map and assign it as an other pointer.

When your function returns, returnMap is copied to the returned value, so the (copied) pointer now really points to garbage.

Optimizer often avoid this last copy, its called "copy elision" (or "Return Value Optimization") and might be the reason of your "normal" behavior. But it doesn't matter, your program has undefined behavior.

like image 117
quantdev Avatar answered Nov 06 '22 01:11

quantdev


It's not luck. You are returning a pointer to a location on the stack. The location is valid and it happens to have the last value that was placed there, until something else changes it.

Here's an example, and I'm borrowing the idea from the other question you link too, which is exactly the same:

#include <stdio.h>

int* foo()
{
    int a = 5;
    return &a;
}

void nukestack()
{
    int a = 7;
    printf("putting 7 on the stack\n");
}

void main()
{
    int* p = foo();
    printf("%d\n", *p);
    nukestack();
    printf("%d\n", *p);
}

The print from the program will be this:

5
putting 7 on the stack
7

The reason is this. We first call foo(), which allocates space on the stack for variable a. We write 5 to this location, then return from the function, releasing that stack space, but leaving the memory untouched. We then call nukestack(), which allocates space on the stack for its own variable a. Because the functions are so similar, and the variables are the same size in both functions, their memory locations happen to overlap.

At this point the new a variable will still have the old value. But we now overwrite the 5 with 7. We return from the function and our old pointer p still points to this same location, which now has a 7 there.

This is undefined behavior and you're technically breaking the rules if you rely on it. With most compilers you will also get a warning when you return a pointer to a local variable, and warnings should really never be ignored.

like image 35
Flawe Avatar answered Nov 05 '22 23:11

Flawe