0
#include <iostream>
#include <cstring>

class Foo {
public:
    uint32_t m_Size;
    char *m_Data;

public:
    Foo() = default;

    Foo(const char *pieceOfString) {
        printf("Foo Created!\n");
        m_Size = strlen(pieceOfString);
        m_Data = new char[m_Size];
        memcpy(m_Data, pieceOfString, m_Size);
    }

    ~Foo() {
        printf("Deleted Foo. ");
        delete[] this->m_Data;
    }
};

class Entity {
public:
    Foo m_Name;

public:
    Entity(const Foo &name){
        this->m_Name=name;
    }

    ~Entity(){
        printf("Deleted entity. ");
    }
};


int main() {

    Foo* apple=new Foo("something");
    Entity entity=Entity(*apple);


    return 0;
}

As the result of the code above, my console output was:

Foo Created!
Deleted Entity. Deleted Foo.

If a new object is created with the new operator, delete or delete[] operator has to be used in order to free the corresponding memory blocks of the heap. In my example below, I had not used the delete keyword to destruct Foo object (which was created by new), however the destructors of the classes were executed properly. I suppose the automatic destruction of the entity object involves calling the destruction of apple as it is a member of entity. But I am not sure about it.

If I write delete apple, it gives me free(): double free detected in tcache 2.

Any help is appreciated!


Answer:

After making some research and reading the comments, I can answer my question: Why destructor is automatically called in case of new operator? The destructor is not automatically called in case of new operator. In the example there is a variable created on the stack called entity. Because it goes out of scope, first its user-defined destructor is called. That is why Deleted Entity is written on console. After that, it continues to destruct the members. There is only one with Foo type and Foo class has also got a user defined destructor. That is why Deleted Foo appears on the output and the block on the heap pointed by entity.m_Name.m_Data is freed up due to delete[] this->m_Data; as it is also in the destructor. Because the apple object and the m_Name member of the entity points to the same place, calling delete apple; was indicating free(): double free detected in tcache 2. So the user-defined destructors of Foo and Entity were called due to the stack allocated entity was going out of scope.


However, this case must be avoided as the example violates the rule of three: The apple object and the m_Name member of the entity points to the same place.

Fox1942
  • 276
  • 2
  • 18
  • 3
    It isn't. `Foo m_Name;` creates a new object. And that object is not allocated with `new`. – user253751 Nov 11 '20 at 17:42
  • 3
    You violate the rule of 3/5/0. The `m_data` object in `apple` and `entity` point at the same memory. The `entity` destructor will delete it. `delete apple` will also delete it, but not calling `delete apple` will leak that memory. – 1201ProgramAlarm Nov 11 '20 at 17:50
  • 1
    The code changed a bit since my last comment so I deleted. This is a violation of the rule of 3/5/0: Related: [https://en.cppreference.com/w/cpp/language/rule_of_three](https://en.cppreference.com/w/cpp/language/rule_of_three) – drescherjm Nov 11 '20 at 18:03
  • 3
    Bizarre! `Deleted String.` isn't even in the code, I have no idea why that would have been output to the console. – Eljay Nov 11 '20 at 18:07
  • 1
    I think the output matches the first code posted. There was code that was changed in the initial edit window that does not show up as revision 1. The initial code was simpler. I think only a std::string member for Foo – drescherjm Nov 11 '20 at 18:15
  • 2
    Note that the output messages are incorrect; nothing here gets deleted, so the code ought to report "Destroyed Foo. " and "Destroyed Entity. ". – Pete Becker Nov 11 '20 at 19:24
  • @1201ProgramAlarm But if I call "delete apple", it gives me "double free detected error". So i suppose the user defined destructor of apple is already called. – Fox1942 Nov 12 '20 at 10:59
  • @PeteBecker Yeah, there was a misspelling in the console output. I corrected "Destroyed String" to "Destroyed Foo". But in the destructor of Foo there is delete[] this->m_Data; as I am creating m_Data with new operator. – Fox1942 Nov 12 '20 at 11:02
  • I will check the rule of 3/5/0. Thanks! – Fox1942 Nov 12 '20 at 11:02
  • 1
    @Tom -- in case I was too subtle, my point was about the difference between "Deleted xxx" and "Destroyed xxx". In the destructor you know that the object is being destroyed. That could be because it was created with `new` and then deleted, but it could also be because it was created on the stack and simply went out of scope, with no `delete`. – Pete Becker Nov 12 '20 at 14:23
  • Thank you guys! Now I clearly recognized what the problem was. – Fox1942 Nov 12 '20 at 16:13

0 Answers0