-3

I'm just trying this out of curiosity. I have a struct with a constructor and a copy constructor and trying to initialize the struct using the copy constructor in the main, while at the same time within the main, implementing memory allocation to the pointer to a struct. Copy construct initialization works alright, but when I try to free it before the main return, it causes an assertion error in the heap.

    #include <stdio.h>
    #include <malloc.h>

    typedef struct tagInfo
    {
        int iX;
        int iY;

        tagInfo() {};

        tagInfo(int x, int y)
            : iX(x), iY(y) {};

        ~tagInfo() {};

    }INFO;

    int main (void)
    {
        INFO* pInfo = (INFO*)malloc(sizeof(INFO));

        pInfo = &INFO(10, 10);

        free(pInfo);

        return 0;
    }

How can I safely free the above pointer without causing assertion errors?

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
Hyun Kwak
  • 13
  • 3
  • 4
    Don't spam tags! This is not valid C code! – StoryTeller - Unslander Monica Jan 10 '17 at 09:09
  • Seeing that it's C++, you should use `new`/`delete`. In addition to that - storing a memory address of a temporary, and then using it (in `free`) is UB (nevermind creating a memory leak by not freeing `malloc`ed space). – Algirdas Preidžius Jan 10 '17 at 09:10
  • 2
    You are making a mess by mixing C idioms into C++ code without a clear understanding of the implications. The way to learn C++ well is not by trial and error, but by starting at the bottom, and approaching it without bias from previously learned languages. [Pick a good book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) for beginners and take it step by step. – StoryTeller - Unslander Monica Jan 10 '17 at 09:13

3 Answers3

3

malloc and free should not be used in C++, as they do not deal with construction/destruction of objects.


In modern C++ you should use std::unique_ptr if you want to model unique ownership, or std::shared_ptr if you want to model shared ownership - these are called "smart pointers" and provide a safe way of managing dynamic memory that automatically deals with deallocation/destruction. Example:

int main (void)
{
    auto pInfo = std::make_unique<INFO>(10, 10);

    return 0;
}

If you really want to go down the road of manual memory management, you must use new (for allocation+construction) and delete (for deallocation+destruction). Example:

int main (void)
{
    INFO* pInfo = new INFO(10, 10);
    delete pInfo;

    return 0;
}
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
0

I think the basic misunderstanding is that a copy constructor does not copy the contents of one object into an (already existing) other object of the same type, but rather generates a new object, which is initialized based on the contents of the object to be copied from.

In your code, you reserve memory for an object of type INFO using malloc and let pInfo point to that memory.

Next, with pInfo = &INFO(10, 10) you instantiate a new object of type INFO on the stack (not on the heap), and let pInfo point to the memory address of this object (which is on the stack!). BTW, you loose the reference to your malloc-ed memory, as pointer pInfo does not point to the malloc-ed address any more, but on the new object.

free(pInfo) is critical, as you free a memory address which has not been allocated with malloc before.

Actually, you should do the following:

INFO* pInfo = new INFO(10, 10);
...
delete pInfo;
Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
  • Thanks! This was the type of answer I was looking for! I know I should use new delete in a C++ code, but I just wanted to try it out using malloc and free, and compare. Thanks for being cool! – Hyun Kwak Jan 10 '17 at 09:23
0

In general, you can do that with placement new, but it is highly discouraged:

// allocate
void* pInfoMem = malloc(sizeof(INFO));
// construct
INFO* pInfo = new(pInfoMem) INFO(10, 10);

// destruct
pInfo->INFO::~INFO();
// free
free(pInfoMem);

But then you need to manually call the destructor before the freeing.

It is much easier to just do (as other answers mention):

INFO* pInfo = new INFO(10, 10);
delete pInfo;
EmDroid
  • 5,918
  • 18
  • 18