0
votes

In C++, if I have some dynamically allocated memory using malloc, can I free the same by calling free() from destructor and then explicitly call the destructor via class object?

Trying to do that but getting an exception.

Is it now allowed?

So here I'm explicitly calling the destructor. Is this allowed? I mean, I'm calling it to free memory. I did read that after the scope, the destructor is called implicitly. Does this mean the free() will try to happen twice?

My code snippet:

class School
{
    int a;
};

class Test
{
    public:
    School* school;
    void Run()
    {
        school = (School*)malloc(sizeof(School));
    }
    
    ~Test()
    {
        if (NULL != school)
        {
            free(school);
            school = NULL;
        }
    }
};

int main()
{
    Test t;
    t.Run();
    t.~Test();
    return 0;
}
2
Which destructor are you calling? Can you show some code? - tkausl
Use new/delete and don't call the destructor yourself, look into smart pointers, it would save you some work. Show us your code for better assessment. - anastaciu
Not only is calling free to release memory acquired via malloc allowed, it is the only correct way to do it. But in C++ you should generally not be using malloc in the first place. If you are getting an exception or a crash, then there is an error in your code, but it isn't from passing a malloced pointer to free. Please share a minimal reproducible example. Otherwise, it is very difficult to guess where you went wrong. - François Andrieux
Yes, let me share. One minute. - Curiosity
@Curiosity I can make the class fall apart with a one line program: int main() {Test t;} Then here it falls apart with a three line program: int main() { Test t. t.Run(); Test t2 = t; }. - PaulMcKenzie

2 Answers

1
votes

Your code destroys t twice. It is destroyed first when you call the destructor and then again when it goes out of scope. You cannot create one object and then destroy two objects.

0
votes

You can explicitly call the destructor, and that has sense whenever you create the object using an placement new.

You may get an exception if you have the opposite order of operations. First you need to call the destructor, as it needs to free all the resources that the object may have allocated. You need to call the free function only after all resources of the object are deallocated/destroyed. For example:

struct S {
    ~S() {
        delete ptr;
    }
    int *ptr;
};

int main() {
    char *buf = (char*) malloc(sizeof(S)) ;
    S *s = new (buf)S();
    // Do not call free here as the destructor needs to access the s.ptr:
    //free(buf);
    s->~S();
    free(buf);

    return 0;
}