2

I have the following code

#include <iostream>

struct mystruct
{
    float x;
};

void fun(mystruct* ptr)
{
    mystruct str = {10};
    ptr = &str;
    std::cout<<"bbq";
}

class cls
{
public:
   mystruct* ptr;
   void fun()
   {
        mystruct str = {10};
        ptr = &str;
        std::cout<<"bbq";
   }
};

int main()
{
    mystruct* ptr = new mystruct;
    fun(ptr);
    std::cout<<"bbq";

    cls obj;
    obj.fun();
    std::cout<<"bbq";

}

At first pointer ptr is set in function fun to address of local structure. When function returns local structure gets destroyed as expected.

But then there is method in class that does the same with member pointer, but after method retrurns and im back in main member pointer is still set. Aren't method local variables destroyed after method returns ?

user1387886
  • 122
  • 1
  • 7

3 Answers3

4

Your first example isn't setting the pointer that was passed, it is setting a local copy of the pointer since it was passed by value. You need to pass by reference in order to use the actual argument:

void fun(mystruct*& ptr);

Local variables are destroyed after the function returns. But even after you see a value inside the pointer that was set to a local variable, you can't assume that the local variable was not destroyed. If you dereference the pointer any time after assigning it to an expired object, your program then has Undefined Behavior.

Related: Can a local variable's memory be accessed outside its scope?

Community
  • 1
  • 1
David G
  • 94,763
  • 41
  • 167
  • 253
1

The code is pretty strange. For example in this function:

void fun(mystruct* ptr)
{
    mystruct str = {10}; // create a structure
    ptr = &str;  // make ptr point to it
    std::cout<<"bbq";
}

ptr is being set to something, but then it is never used. ptr is being passed by value so there is no way it can have an effect outside this function.

And here:

class cls
{
public:
   mystruct* ptr;
   void fun()
   {
        mystruct str = {10}; // create local variable
        ptr = &str;  // make ptr point to it
        std::cout<<"bbq";
   }
};

You are setting the class member ptr to point to a local variable, but then that variable is destroyed when the function returns, so ptr is left pointing to garbage. ptr isn't being used again in your example, so no harm done, but it is still strange.

And in your main:

int main()
{
    mystruct* ptr = new mystruct; // make ptr point do a dynamically allocated object.
    fun(ptr); // call fun with a copy of the pointer
    std::cout<<"bbq";

    cls obj;
    obj.fun();
    std::cout<<"bbq";
    // That object that ptr is pointing to is never deleted.

}

There's no particular harm in not deleting something you allocated in this case, since this is the end of your program, but it's good practice to delete your dynamically allocated objects in general.

Vaughn Cato
  • 63,448
  • 5
  • 82
  • 132
1

We could induce a failure by doing this:

struct mystruct
{
    float x;
    ~mystruct() { x = 99; }
};


class cls
{
public:
   mystruct* ptr;
   void fun()
   {
        mystruct str = {10};
        ptr = &str;
        std::cout<<"bbq";
   }
   void fun2()
   {
       std::cout << ptr->x << std::endl;
   }
};

... 
  obj.fun();
  obj.fun2();

Now, it may happen that obj.fun2(); prints 99, or it may show some random other number, or it may crash. This is because the "use of an object that has been destroyed is undefined behaviour" - undefined behaviour means that the C++ standard does not define what happens, and "anything could happen", including crashing or hanging, or it works "as you expect". But the object will be destroyed. Since the original code doesn't actually USE ptr after the object it points to was destroyed, nothing bad happens (in fact, it's not even undefined behaviour in the example code - it is only undefined to "use pointed at object after the object has been destroyed").

Edit:

this code, however:

mystruct* ptr = new mystruct;
fun(ptr);
std::cout<<"bbq";

causes a memory leak, since ptr is never deleted (and if fun where to actually modify ptr outside of the function itself, e.g by using mystruct *&ptr as the argument, then you would have a memory block for mystruct that is no longer referenced, which is an even worse memory leak - and of course a value in ptr that points to destroyed object, so you can't use ptr anyway)

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227