简体   繁体   中英

Using malloc and new - C++

I'm new to C/C++ and developing a C++ application. There I have a problem with new and malloc. My application is bit complex and there are some C structs as well. At some point, I wanted to allocate new memory for Class of type MyData (which contains a deque) and later I assigned that pointer to a pointer in a C struct. Smaller version of my code is as follows.

#include <deque>
class MyData 
{
public:
    MyData(){};
    ~MyData() {};

    std::deque<int>& GetDequeMyDataSet() {return deque_MyDataSet; };

private:
    std::deque<int>     deque_MyDataSet;//contains ohlc data for the symbol   
};

int _tmain(int argc, _TCHAR* argv[])
{
    MyData* pMyData = new MyData();
    MyData* p_Data = (MyData*)malloc(sizeof(MyData*));
    p_Data = pMyData;
    p_Data->GetDequeMyDataSet().push_back(10);
    p_Data->GetDequeMyDataSet().push_back(11);
    //.... Several other push back and operations releated to this deque goes here. 
    delete pMyData;// At the end I free both memories.
    free(p_Data);
    return 0;
}

After allocating memory for both pointers I used GetDequeMyDataSet() method on malloc pointer (p_Data). My problem is whether it is ok to push_back items to the deque on this malloc pointer, as I have allocated memory for the pointer only? Can malloc handle dynamic memory allocation for deque?

Here's your situation in simplified terms:

void * p = malloc(1);
void * q = malloc(1);

q = p;

free(q);
free(p);

Can you spot the problem?

No point in using deque if you mostly push_back elements. It's slower in pushing back elements and faster in push_front compared to vectors insert. Also using malloc is just asking for problems. Same goes for new, use std::shared_ptr or std::unique_ptr if you really need to allocate your class object dynamically. They will take care of memory deallocation for you.

 #include <vector>

 class MyData 
 {
 public:
     MyData() {};
     ~MyData() {};
     std::vector<int>& GetMyDataSet() { return m_myDataSet; }
 private:
     std::vector<int> m_myDataSet;
 };

 int _tmain(int argc, _TCHAR* argv[])
 {
     MyData myData;
     myData.GetMyDataSet().push_back(10);

     //or dynamically
     auto pMyData = std::make_shared<MyData>();
     pMyData->GetMyDataSet().push_back(10);


     return 0;
 }

The difference between malloc and new is that the first does not call the class's constructor while the later does. The constructor in turn calls the constructors of the member variables as is the case with deque_MyDataSet in this case. So what you do will not call the constructor of the deque.

Always use new in C++ to avoid problems later on. And to ensure everything is initialized correctly.

Mixing malloc() and new is a bad idea. Also, what is a "C class"?

Anyway, this:

MyData* p_Data = (MyData*)malloc(sizeof(MyData*));

is flat out wrong, you're not allocating the correct amount of memory. You mean:

MyData* p_Data = (MyData *) malloc(sizeof *p_Data);

since you must have the actual size of the MyData structure being pointed at. Your code allocated only enough room for the the pointer , which is not what you mean.

Note that the cast is required in C++, but is bad practice in C .

My problem is whether it is ok to push_back items to deque on this malloc pointer as it has allocated memory for pointer only?

Normally, it is ok to push_back items into an object no matter how it was initialized (allocated dynamically or on the stack). In this case though, p_Data was allocated, but not initialized at all.

To see this, you need to understand the difference between malloc and new:

malloc is the C function that allocates a block of memory and returns a (void) pointer to it. The reason it exists in C++ is because C++ was initially compatible with C and able to use it's libraries (and nowadays it is required for backwards compatibility.

new is the C++ operator that allocates a block of memory, interprets it as an object, and calls the constructor for that object transparently. The two functions are not interchangeable.

When you allocate memory for an object, always use new. malloc will not call the constructor of your object (nor will free call the destructor of your object).

Equivalent code:

class MyData { /* same as in your question */ };

// 1: normal C++ dynamic object allocation
MyData* pMyData = new MyData();

// 2: allocate through malloc and call constructor through placement new 
void*   block = (MyData*)malloc(sizeof(MyData)); // allocate sizeof(MyData) bytes
MyData* pMyData = new(block) MyData(); // call constructor on block memory

This means that if you use malloc and free, your objects are not initialized, even though normally (intuitively) you'd expect them to be.

TL:DR: Never use malloc and free in C++.

After allocating for memory both pointers I used GetDequeMyDataSet() method on malloc pointer(p_Data)

That shouldn't have worked. The malloc'd pointer should not be initialized (allocated yes, initialized no).

On top of that, since you assign p_Data = pMyData; , your call to free will attempt to release memory already assigned by the delete statements (since both point to the same address).

That should be seen as an access violation error.

In C++ there is often no need to allocate things dynamically. You just create a new object when you need one:

int _tmain(int argc, _TCHAR* argv[])
{
    MyData myData;   // No pointers, no new

    MyData* p_Data = &myData;   // Create a pointer to myData, if you need one
    p_Data->GetDequeMyDataSet().push_back(10);
    p_Data->GetDequeMyDataSet().push_back(11);
    //.... Several other push back and operations releated to this deque goes here. 

    // Nothing to delete or free here

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM