0

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?

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
Anupama Pathirage
  • 631
  • 2
  • 10
  • 22
  • first of all `sizeof (MyData*)` would be wrong even in C... – Dariusz Feb 25 '13 at 11:43
  • Why are you even using malloc? – R. Martinho Fernandes Feb 25 '13 at 11:43
  • If I can make two suggestions: [regarding pointers](http://klmr.me/slides/modern-cpp/) and [The Definitive C++ Book Guide and List](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). –  Feb 25 '13 at 11:43
  • What are you trying to do here? This line `MyData* p_Data = (MyData*)malloc(sizeof(MyData*));` doesn't make any sense. –  Feb 25 '13 at 11:52
  • What I actually need is to refer the same memory pointer allocated using new operator within my C code as well. So if I add the elements to deque using new created pointer(i.e. pMyData), then is p_Data can be allocated to only size of pointer only. So if I modify to code to below why is it wrong? MyData* pMyData = new MyData(); MyData* p_Data = (MyData*)malloc(sizeof(MyData*)); p_Data = pMyData; pMyData->GetDequeMyDataSet().push_back(10); pMyData->GetDequeMyDataSet().push_back(11); delete pMyData; free(p_Data); return 0; – Anupama Pathirage Feb 25 '13 at 12:10
  • @user - You don't have to manually allocate space for everything, in C++ this is done automatically for you. `MyData* p_Data = pMyData;` is enough to create a second pointer to the same object. – Bo Persson Feb 25 '13 at 12:17

6 Answers6

6

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?

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 2
    @FrerichRaabe there are five problems: UB, use of pointers, use of `malloc`, use of `void*` and missing `std::`. –  Feb 25 '13 at 11:48
  • @Zoidberg: Only if you treat this particular piece of code as C++; and funnily enough your five issues didn't even include the two I thought of (which are true even if you consider this as C). ;-) – Frerich Raabe Feb 25 '13 at 11:52
2

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;
 }
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.

Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176
0

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.

Community
  • 1
  • 1
unwind
  • 391,730
  • 64
  • 469
  • 606
  • What I actually need is to refer the same memory pointer allocated using new operator in my C code. – Anupama Pathirage Feb 25 '13 at 12:00
  • I believe he actually attempts to allocate space for the pointer. Former Java programmer, perhaps? – Bo Persson Feb 25 '13 at 12:04
  • MyData* pMyData = new MyData(); MyData* p_Data = (MyData*)malloc(sizeof(MyData*)); p_Data = pMyData; pMyData->GetDequeMyDataSet().push_back(10); pMyData->GetDequeMyDataSet().push_back(11); delete pMyData; free(p_Data); return 0; – Anupama Pathirage Feb 25 '13 at 12:14
0

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.

utnapistim
  • 26,809
  • 3
  • 46
  • 82
  • Thanks lot for valuble ideas. "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)." Although same points to the same area, isn't it not necessary call delete for every new, and free for every malloc? – Anupama Pathirage Feb 25 '13 at 12:20
  • Not as such; It is necessary to call delete/free for every memory block (depending on how it was allocated - free for malloc and delete for new). In your case, you call both delete and free for the address allocated by new (causing an access violation/double delete) and none of them on the address allocated by malloc (that address is lost, when you do `p_Data = pMyData;`) – utnapistim Feb 25 '13 at 13:30
0

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;
}
Bo Persson
  • 90,663
  • 31
  • 146
  • 203