3

The closest thread to my question is here. I am trying to compile the following code with gcc:

#include <malloc.h>

class A
{
public:
  A(){};  
  ~A(){};
};//class A

int main()
{
  A* obj = (A*) malloc( sizeof(A) );
  if(obj==0) return 1 ;
  obj->A::A(); /*error: invalid use of 'class A' */
  obj->A::~A();
  free(obj);
  return 0;  
};//

From the command line I compile the code with:

$ g++ -o main main.cpp  
main.cpp: In function 'int main()':  
main.cpp:22: error: invalid use of 'class A'

Can you please point me in the right direction?

Community
  • 1
  • 1
grayasm
  • 973
  • 2
  • 10
  • 14
  • possible duplicate of [C++, is it possible to call a constructor directly, without new?](http://stackoverflow.com/questions/2494471/c-is-it-possible-to-call-a-constructor-directly-without-new) – kennytm Jul 20 '10 at 20:06
  • 3
    Why are you doing it this way? Are you trying to avoid exceptions when new fails? Just use `new (nothrow)` then test for NULL. – Amardeep AC9MF Jul 20 '10 at 20:10
  • @Amardeep, one example I can think of is web-service server implementation, where you cannot delete objects until they are serialized and when they are serialized you don't have the thread of control, so you can not call destructor, the tool-kit or framework has to `free` that. the memory provided and managed for you is through `malloc` then there is no other way but to use this. *(and if they do not provide customized `new` operator, which does allocation on their heap and deletes them as well.)* – Ramadheer Singh Jul 20 '10 at 20:21
  • @Amardeep : but I see that it does not look like that case. so +1 to your question. – Ramadheer Singh Jul 20 '10 at 20:41
  • @Gollum: I don't believe that. Do you have any reference to this web server. – Martin York Jul 20 '10 at 21:23
  • @Martin York, gsoap toolkit is the one I was referring to ( but it does provide its own `soap_new_` ). If it did not provide with that custom new, `placement-new` is the only way I can think of. http://www.cs.fsu.edu/~engelen/soap.html - look for memory management – Ramadheer Singh Jul 20 '10 at 21:49

4 Answers4

8

You want a placement-new instead.

void* ptr = malloc(sizeof(A));
A* obj = new(ptr) A;
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • how does the allocator work in this case, same way as it does its' own heap? – Ramadheer Singh Jul 20 '10 at 20:08
  • 1
    @Gollum: No allocation is done if you use placement new. It just set `ptr` as `this` and calls the constructor. – kennytm Jul 20 '10 at 20:09
  • @KennyTM, was talking about allocating a big buffer and then doing multiple `placement-new` for all the objects I need to allocate on that big-buffer(like n strings). (how would n objects get placed, it should have its own algorithm to fit those objects in - what about `fragmentation ` – Ramadheer Singh Jul 20 '10 at 20:13
  • 1
    @Gollum: Placement new has **nothing** to do with allocation. It just *places* `this` on the argument it takes than calls the constructor. In my answer it's the `malloc` line that's doing the allocation. – kennytm Jul 20 '10 at 20:26
  • ok, thanks a lot. I think I need to read about it, I have doubts about placing more than one object on the `malloced` memory using `placement-new` which I guess is not possible. – Ramadheer Singh Jul 20 '10 at 20:36
  • @Gollum: Why wouldn't it be possible? That's what `std::vector` *does*. – GManNickG Jul 20 '10 at 20:40
  • @GMan, correct me if wrong : let's say I put two `strings`, two `Some_Class_A` object, few other objects here and there. When I delete some object X, wouldn't it leave hole and thus fragmentation(if done for many-randomly). so my question is, how does it do all that management? assume, I did allocate 10K block and playing in that memory doing `placement-new` in it for all the objects. In case of vector, the object size is fixed and known at compile time. – Ramadheer Singh Jul 20 '10 at 21:00
  • 1
    @Gollum: That's perfectly fine. You may need to play around with alignment issues but nothing is stopping you technically from putting a 10K (1 byte) objects or 5 (2K) objects or any combination you can think of into a 10K block or allocated space. Note: The block is allocated by you and thus it is your responsibility to manage the fragmentation and eventually release the memory as appropriate. As for vector the size is not known at compile time *that is why vector is so useful it is sized at runtime). – Martin York Jul 20 '10 at 21:29
  • @Martin York, Thank you very much for the explanation :-) . I meant the size of objects kept in `vector` not the size of vector itself. `std::vector` ----> size of ClassA is known at compile time – Ramadheer Singh Jul 20 '10 at 21:44
  • @Gollum: What do you mean "a hole"? Firstly, you wouldn't `delete` anything made with placement new, you just call the destructor. Secondly, even if you could you'd still just have a hunk of memory, delete doesn't somehow steal part of it. – GManNickG Jul 20 '10 at 23:41
  • @GMan, **a hole:** if I placed 1000 object of 10 bytes in 10K memory I allocated with `malloc` and destroyed a few randomly from the which happen to be scattered in the middle of the block it will create small **holes** of 10 bytes (`fragmentation`) and when I go ask it to place some object of 11 bytes it will fail. so I was asking about how does the `placing` work internally. does it place these objects in contiguous memory or looks for these kind of holes too? I might not be explaining this well enough, confused enough people. apologies. – Ramadheer Singh Jul 21 '10 at 00:42
  • @Gollum: No problem. :) Placing literally just puts an object where you say, so fragmentation is a totally separate issue. – GManNickG Jul 21 '10 at 03:57
6

You can't call a constructor on an object; a constructor can only be called in the creation of an object so by definition the object can't exist yet.

The way to do this is with placement new. There's no need to cast your malloc return. It should be void * as it doesn't return a pointer to an A; only a pointer to raw memory in which you plan to construct an A.

E.g.

void* mem = malloc( sizeof(A) );

A* obj = new (mem) A();
obj->~A();

free(mem);
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
2

There is no need for malloc business in C++. Simply do:

A* obj = new A();

new allocates the memory and calls the constructor for you.

And, to destroy it, do:

delete a;

delete calls the deconstructor method and frees the memory.

Donald Miner
  • 38,889
  • 8
  • 95
  • 118
2

Since you are using C++, falling back to malloc is unnecessary. You can write it in terms of operator new

int main() {
  if(A* obj = new (std::nothrow) A()) {
    delete obj;
    return 0;
  }
  return 1;
}

The nothrow version of new returns a null pointer if allocation fails, instead of throwing an exception.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212