2

Created a simple class to test deleting Objects and this function will be called from another language but I ran into some weird issues I can't explain.

I have class with functions that can destroy instance of it and set the pointer to null.

1.Destructor is called when delete is used in the main function which is expected:

using namespace std;

//Forward declaration:
class Motor;


void DestroyMotor(Motor** motor)
{
    if (motor != nullptr)
    {
        //(*motor)->~Motor();
        delete *motor;
        *motor = nullptr;
    }
}

void DestroyMotor(Motor*& motor)
{
    delete motor;
    motor = nullptr;
}

class Motor
{
public:
    Motor();

    ~Motor();

private:

};

Motor::Motor()
{
    cout << "Motor Created" << endl;
}

Motor::~Motor()
{
    cout << "Motor Destroyed" << endl;
}

int main()
{

    {
        Motor *myMotor = new Motor();

        if (myMotor == nullptr)
            cout << "IS null" << endl;
        else
            cout << "NOT null" << endl;

        delete myMotor;
        myMotor = nullptr;

        if (myMotor == nullptr)
            cout << "IS null" << endl;
        else
            cout << "NOT null" << endl;
    }

    cin.get();
    return 0;
}

Output:

  • Motor Created
  • NOT null
  • Motor Destroyed
  • IS null

2.Destructor is NOT called when delete is used in one of the DestroyMotor functions (Bug?):

int main()
{

    {
        Motor *myMotor = new Motor();

        if (myMotor == nullptr)
            cout << "IS null" << endl;
        else
            cout << "NOT null" << endl;

        //Free myMotor;
        //DestroyMotor(myMotor);
        DestroyMotor(&myMotor);

        if (myMotor == nullptr)
            cout << "IS null" << endl;
        else
            cout << "NOT null" << endl;
    }

    cin.get();
    return 0;
}

Output:

  • Motor Created
  • NOT null
  • IS null

3.The problem in #2 is fixed if I move the class to the top of those two DestroyMotor functions and the destructor is now being called.

using namespace std;

class Motor
{
public:
    Motor();

    ~Motor();

private:

};

Motor::Motor()
{
    cout << "Motor Created" << endl;
}

Motor::~Motor()
{
    cout << "Motor Destroyed" << endl;
}


void DestroyMotor(Motor** motor)
{
    if (motor != nullptr)
    {
        //(*motor)->~Motor();
        delete *motor;
        *motor = nullptr;
    }
}

void DestroyMotor(Motor*& motor)
{
    delete motor;
    motor = nullptr;
}

int main()
{

    {
        Motor *myMotor = new Motor();

        if (myMotor == nullptr)
            cout << "IS null" << endl;
        else
            cout << "NOT null" << endl;

        //delete myMotor;
        //myMotor = nullptr;

        //Free myMotor;
        //DestroyMotor(myMotor);
        DestroyMotor(&myMotor);

        if (myMotor == nullptr)
            cout << "IS null" << endl;
        else
            cout << "NOT null" << endl;
    }

    cin.get();
    return 0;
}

Output:

  • Motor Created
  • NOT null
  • Motor Destroyed
  • IS null

Can anyone explain what exactly is going on with #2 and why moving the class to the top fixed the issue? I mean, I used forward declaration but that never solved the issue.

Programmer
  • 121,791
  • 22
  • 236
  • 328
  • 2
    Couldn't find an exact dupe, but the explanation is [here](https://stackoverflow.com/questions/4325154/delete-objects-of-incomplete-type). (tl;dr: it's undefined.) – molbdnilo Apr 24 '18 at 04:01
  • 1
    That's a bit tricky actually, I wonder why it is UB instead of either OK or requiring diagnostic. Maybe I have made the same mistake with pImpls in production and never realized it – M.M Apr 24 '18 at 04:01
  • @molbdnilo Good link. Weird since I declared the class too not just the forward declaration from the question you linked. – Programmer Apr 24 '18 at 04:10
  • @Programmer *If the object being deleted has incomplete class type at the point of deletion..* – Gaurav Sehgal Apr 24 '18 at 04:15
  • 2
    @Programmer When `DestroyMotor` is being defined, the `Motor` type is incomplete. – molbdnilo Apr 24 '18 at 04:16
  • Ok. That makes sense and thanks to both of you. Would have been better is the compiler gave a warning. – Programmer Apr 24 '18 at 04:18

0 Answers0