-2

In the code below, function localObjReurn() returns a local object which has raw pointer to heap. When this is returned, the local object gets destroyed and the destructor deletes the heap memory and pointer. In main, steve gets a copy of this destroyed object. When steve is printed, it shows valid data and on getting destroyed at end of the scope of main, there is no crash due to multiple freeing of the same memory. Why?

#include <iostream>
#include <cstring>

class Player{
private:
    char *ptr;
    
public:
    Player(char *c)
    {
        ptr = new char[strlen(c) +1];
        strcpy(ptr, c);
    }
    Player(const Player &p)
    {
        ptr = new char[strlen(p.ptr) + 1];
        strcpy(ptr, p.ptr);
    }
    ~Player()
    {
        delete [] ptr;
    }
    char * getData()
    {
        return ptr;
    }
};

Player localObjReturn()
{
    Player tempObj("Weinstein");
    return tempObj;
}

int main()
{
    Player steve {localObjReturn()};
    
    std::cout << steve.getData();
}
user3768448
  • 5
  • 1
  • 7
  • 2
    " there is no crash due to multiple freeing of the same memory" .. what memory do you expect to be freed more than once? Your constructors are such that each object gets a `new`ed `ptr`. You are leaking but not double freeing – 463035818_is_not_an_ai Jun 28 '21 at 19:01
  • 4
    anyhow, crashes are not something you can rely on. When code has undefined behavior anything can happen, including nothing, or appearing to work – 463035818_is_not_an_ai Jun 28 '21 at 19:02
  • 1
    related: https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three – 463035818_is_not_an_ai Jun 28 '21 at 19:03
  • It seems you posted an identical question a 2nd time, except that [the first time you claimed the program did not crash](https://stackoverflow.com/questions/68167600/c-returning-local-object-with-pointer-to-heap-by-value-doesnt-crash-the-pro). Which one is it? – Sam Varshavchik Jun 28 '21 at 19:03
  • @SamVarshavchik only the title says "causes crash" question still says "there is no crash", though its a little confusion, I don't understand what OP is asking either – 463035818_is_not_an_ai Jun 28 '21 at 19:04
  • 1
    Handy reading: [Copy Elision](https://en.cppreference.com/w/cpp/language/copy_elision). You'll probably find that the copy constructor is never called. – user4581301 Jun 28 '21 at 19:04
  • @user4581301 not sure if that is relevant. Even if the copy constructor is called, I don't see what would be double freed – 463035818_is_not_an_ai Jun 28 '21 at 19:08
  • You added an operator-overloading tag. There are no operators being overloaded. – user4581301 Jun 28 '21 at 19:08
  • 1
    And now the title has been edited to say the opposite of what it was, and the same claim as the first question. So, this should be closed as a dupe. – Sam Varshavchik Jun 28 '21 at 19:09
  • Does this answer your question? [What is the rule of three?](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) – n. m. could be an AI Jun 28 '21 at 19:10
  • There is no crash. Since the returned object has a pointer to heap and since it's destroyed at end of function when a copy of this is received in main, how does the copy happen. If it is memberwise copy, then new objects pointer is also pointing to destroyed heap location. Thats the confusion. – user3768448 Jun 28 '21 at 19:10
  • Not relevant until you step through the program with a debugger or put a print statement in the copy constructor to help trace what's going on. – user4581301 Jun 28 '21 at 19:10
  • 2
    Let me ask a somewhat blunt question. Do you know what a copy constructor is? – n. m. could be an AI Jun 28 '21 at 19:13
  • The copy probably doesn't happen at all. Neither does the destruction of the local object. The compiler's too smart. Example: https://godbolt.org/z/MvnvsMqGE – user4581301 Jun 28 '21 at 19:13

1 Answers1

2

there is no crash due to multiple freeing of the same memory. Why?

Take a look at what the copy constructor does:

Player(const Player &p)
{
    ptr = new char[strlen(p.ptr) + 1];
    strcpy(ptr, p.ptr);
}

As you can see, the copy doesn't point to the same array. As such, there is no freeing of the same memory. There is freeing of different memory.

... Or there would be if the copy wasn't elided away entirely. A smart compiler should make sure that there was only one object created and thus one freeing of memory.

P.S. Even if there was multiple freeing of same memory, there wouldn't necessarily be a crash. The behaviour of the program would be undefined in that case and you couldn't rely on any particular behaviour.

P.P.S While the copy initialised object won't cause undefined behaviour, a copy assigned one does. The class is broken.

P.P.P.S Player tempObj("Weinstein"); Conversion from string literal to char* is ill-formed in C++ (since C++11; prior to that the conversion was deprecated).

P.P.P.P.S. The copy constructor leaks memory. Try to avoid bare owning pointers. Here is a fixed version of the class:

struct Player {
    std::string name;
};
eerorika
  • 232,697
  • 12
  • 197
  • 326