differences between malloc and operator new..

B

BekTek

Hi..
I'm so sorry about that I've postes so many questions recently.. :)

I'm still confused about the differences between malloc and operator new..
I know that when we work with class object and use operator new/delete, the
ctor and dtor
get called as expected, but malloc and free do not..

But Herbal Sutter mentioned in his greate book 'exceptional c++' about free
storage
and heap..
He said they are differenct and we need to know the differences..

But I'm still confused about they are different..
I've thought actually both new and malloc use heap..

can some clearify me?
 
G

Gianni Mariani

BekTek wrote:
....
can some clearify me?

This is an example where the global operator new is overridden...

#include <iostream>
#include <string>

using namespace std;

void * operator new( size_t size )
{
cout << "our own new operator -- size is " << size << "\n";
return malloc( size );
}

void operator delete( void *pFreeMe )
{
cout << "our own delete operator\n";
free( pFreeMe );
}

class CA
{
public:

CA( std::string strArg ) : strString( strArg )
{
}

void print()
{
cout << strString.c_str() << "\n";
}

private:

std::string strString;
};

int main( int iArgc, char *pcArgv[] )
{
CA *pa = new CA( "funky" );
pa->print();

cout << sizeof( CA ) << "\n";

delete pa;
}
 
M

Method Man

Gianni Mariani said:
BekTek wrote:
...
can some clearify me?

This is an example where the global operator new is overridden...

#include <iostream>
#include <string>

using namespace std;

void * operator new( size_t size )
{
cout << "our own new operator -- size is " << size << "\n";
return malloc( size );
}

void operator delete( void *pFreeMe )
{
cout << "our own delete operator\n";
free( pFreeMe );
}

class CA
{
public:

CA( std::string strArg ) : strString( strArg )
{
}

void print()
{
cout << strString.c_str() << "\n";
}

private:

std::string strString;
};

int main( int iArgc, char *pcArgv[] )
{
CA *pa = new CA( "funky" );
pa->print();

cout << sizeof( CA ) << "\n";

delete pa;
}

Sorry, but I'm a bit confused. How/why does the constructor for class CA get
called if new is overriden? What order would they be called in (I assume:
operator new then ctor)?

Also, I don't know if the above is a good example, because it doesn't really
illustrate why someone would want to override new.
 
L

Larry Brasfield

Method Man said:
This is an example where the global operator new is overridden...

#include <iostream>
#include <string>

using namespace std;

void * operator new( size_t size )
{
cout << "our own new operator -- size is " << size << "\n";
return malloc( size );
}

void operator delete( void *pFreeMe )
{
cout << "our own delete operator\n";
free( pFreeMe );
}

class CA
{
public:

CA( std::string strArg ) : strString( strArg )
{
}

void print()
{
cout << strString.c_str() << "\n";
}

private:

std::string strString;
};

int main( int iArgc, char *pcArgv[] )
{
CA *pa = new CA( "funky" );
pa->print();

cout << sizeof( CA ) << "\n";

delete pa;
}

Sorry, but I'm a bit confused. How/why does the constructor for class CA get
called if new is overriden?

The constructor is called in the same way as is usual, after
a location for the object has been determined or arranged.
Why is it called? To convert raw memory into a proper
instance of the class. This is the constructor's role, to be
distinguished from somehow obtaining raw memory.
What order would they be called in (I assume:
operator new then ctor)?
Yes.

Also, I don't know if the above is a good example, because it doesn't really
illustrate why someone would want to override new.

True, it only illustrates the mechanics of overriding and
shows that the ctor is called after operator new works.
It takes a little more imagination to see that the ability
to define a customized or optimized allocator can be
used to improve the performance of programs. For
example, if it was known in advance that allocations
tended to all occur before releases, a simpler and
hence faster allocator could be written.

A more common override is to define a per-class
operator new and delete. Such an allocator can be
specialized for objects of a certain size which can
permit considerably faster operation.
 
J

Jonathan Mcdougall

BekTek said:
I'm still confused about the differences between malloc and operator new..
I know that when we work with class object and use operator new/delete, the
ctor and dtor
get called as expected, but malloc and free do not..

There is a difference between operator new and the new operator: the
latter calls the former.

The new operator is something you will never see. Basically, it does
two things :

1. calls operator new to get some raw memory
2. calls the object's constructor on that memory

As you can see, fiddling with the new operator would require you to call
constructors by hand, which is impossible.

The first point was a call to operator new. That operator you can
overload as any other operator. Its function is to provide a pointer to
enough memory for the object to construct itself; this is a malloc-like
function and actually, the default implementation is usually written in
terms of malloc().
But Herbal Sutter
:)

mentioned in his greate book 'exceptional c++' about free
storage
and heap..
He said they are differenct and we need to know the differences..

That was a theoritical question.
But I'm still confused about they are different..
I've thought actually both new and malloc use heap..

The standard doesn't require them to do so, but that's what happens in
real life.

Calling malloc() returns a pointer to a block of memory on the heap
which has the given size :

malloc(sizeof(MyClass));

returns a pointer to a block of sizeof(MyClass) bytes. That's raw memory.

new MyClass;

return a pointer to a block of sizeof(MyClass) bytes on which the
constructor was called. So that block is not raw memory: it's a valid
object. That was done in two steps, the steps described above.

The conclusion is : malloc() only allocates raw memory and new allocates
raw memory on which the constructor is called. Something like

// what the new operator does behind your back:

// allocate raw memory
MyClass *p = reinterpret_cast<MyClass*>(malloc(sizeof(MyClass)));

// call constructor
p->MyClass();

Of course that code is invalid since calling constructors is illegal,
but that's what the compiler is doing behind your back. Since we're in
C++, the malloc() call is replaced by a call to operator new :

// allocate raw memory
MyClass *p = reinterpret_cast<MyClass*>(operator new(sizeof(MyClass)));

// call constructor
p->MyClass();

And usually, as I said, operator new is implemented in terms of malloc :

void *operator new(std::size_t size)
{
return malloc(size);
}

though you could override it to call some application-specific functions
(such as memory pool functions).

Jonathan
 
M

Matthias =?ISO-8859-1?Q?K=E4ppler?=

I also have a question here regarding the constructor and destructor calls.
Since malloc and free are C functions, they know nothing about constructor
or destructor calls.
However, in your example, operator 'new' is nothing but a malloc call with a
new look. How would the compiler figure out which constructor to call? If
at all?
In fact, Scott Meyers says in 'Effective C++' that you should never ever use
malloc and free for exactly that reason.

Can you clarify that?

- Matthias
 
I

Ioannis Vranos

BekTek said:
Hi..
I'm so sorry about that I've postes so many questions recently.. :)

I'm still confused about the differences between malloc and operator new..
I know that when we work with class object and use operator new/delete, the
ctor and dtor
get called as expected, but malloc and free do not..

But Herbal Sutter mentioned in his greate book 'exceptional c++' about free
storage
and heap..
He said they are differenct and we need to know the differences..

But I'm still confused about they are different..
I've thought actually both new and malloc use heap..

can some clearify me?


The malloc()/free() family should be avoided in C++, because when used
the constructors and destructors are not called. They work for POD types
only.


On the other hand the operator new/delete family work for all types, so
you had better use them, and NOT the malloc()/free() family.


Free storage and "heap" are the same thing.
 
I

Ioannis Vranos

Jonathan said:
There is a difference between operator new and the new operator: the
latter calls the former.


What is this? There is no guarantee for such a thing. Do you have TC++PL 3?
 
I

Ioannis Vranos

Method said:
Sorry, but I'm a bit confused. How/why does the constructor for class CA get
called if new is overriden?
Implicitly.



What order would they be called in (I assume:
operator new then ctor)?
Yes.



Also, I don't know if the above is a good example, because it doesn't really
illustrate why someone would want to override new.


When you will need to override operator new, you will know it. That is,
in usual applications, never.


You can also define operator new and delete for a specific class, as
members.

Consider this dummy example:


#include <iostream>

class SomeClass
{
static unsigned char buffer[1024];

public:
SomeClass() { std::cout<<"Constructor called!\n"; }
~SomeClass() { std::cout<<"Destructor called!\n"; }

void *operator new(std::size_t size)
{
using namespace std;

cout<<"Class member operator new was called!\n";

return buffer;
}

void operator delete(void *p)
{
std::cout<<"Class member operator delete was called!\n";

}
};

unsigned char SomeClass::buffer[1024];


int main()
{
SomeClass *p= new SomeClass;


delete p;
}
 
G

Gianni Mariani

Matthias said:
I also have a question here regarding the constructor and destructor calls.
Since malloc and free are C functions, they know nothing about constructor
or destructor calls.
However, in your example, operator 'new' is nothing but a malloc call with a
new look. How would the compiler figure out which constructor to call? If
at all?
In fact, Scott Meyers says in 'Effective C++' that you should never ever use
malloc and free for exactly that reason.

Can you clarify that?

Allocation of storage and construction are two separate things. I don't
know what Scott Meyers is saying.

In C++, operator new, is a dynamic storage allocator - that's it. It
can be associated with a class type so that only the class has the
associated operator. e.g.

struct X
{
void operator new ( int size );
};

Or globally (as in my previous example.

However, the constuctor is invoked in many different places, e.g.

---- file.cpp ----

struct X { X(); };

X x; // <- storage allocation done at compile time, contructor
// invoked before main() is called.
// Storage is retrieved when program exits

void f() {
X x; // <- storage allocation at run time (auto) constructor
// invoked every time f() is called.
// Storage is retrieved when f() returns
}

void s() {
static X x; // <- storage allocation is probably compile time
// constructor invoked only the first time s() is called.
// storage is retrieved when program exits
}

void d() {
X * x = new X(); // <-- storage allocation is dynamic
// constructor invoked every time d() is called.
// storage is retrived on "delete x"
}

---------------

There is a way to call the constructor on the storage of your choice,
it's called "placement new" and the syntax is :

void * place = ...;
T * v = new ( place ) T();

This is how you create containers.

I suspect that Scott Meyers says you should never do this :

T * t = (T*) malloc( sizeof( T ) ); // C style dynamic allocation

The example above is how you would normally do in C what "new" does in
C++. You should allways use new/delete in C++.
 
I

Ioannis Vranos

Jonathan said:
There is a difference between operator new and the new operator: the
latter calls the former.


What is the difference between operator new and new operator above? Are
you calling the user-defined one as "new operator"?
 
M

Method Man

As you can see, fiddling with the new operator would require you to call
constructors by hand, which is impossible.

Based on what I just learned in this thread, you won't need to call the ctor
by hand, as it would be called implicitly after invoking the user-defined
new operator. Correct me if I'm wrong.
 
L

Larry Brasfield

[Quotes subject to top-posting fixup.]
Matthias Käppler said:
I also have a question here regarding the constructor and destructor calls.
Since malloc and free are C functions, they know nothing about constructor
or destructor calls.
However, in your example, operator 'new' is nothing but a malloc call with a
new look. How would the compiler figure out which constructor to call?

When a new expression is seen by the compiler, a type is always
explicitly given. For example:
int * pi = new int(3);
or
class Stuff {};
Stuff * ps = new Stuff;
Notice that a type name is always present, so the
compiler can figure out what to construct.
If at all?

Yes, at all, always.
In fact, Scott Meyers says in 'Effective C++' that you should never ever use
malloc and free for exactly that reason.

I don't think he made such a categorical statement to be
applied to operator new replacements. Anyway, the
point of the example was not related to the precise
allocator used. It was simply to show how the global
allocator could be redefined.
Can you clarify that?

Scott's advice relates to using malloc/free to (sort of)
create objects. That is a bad idea because they only
deal in raw memory. It is by the constructor's action
that an object can be made over raw memory and by
the destructor's action that an object becomes merely
raw memory.
 
K

Karl Heinz Buchegger

Method said:
Based on what I just learned in this thread, you won't need to call the ctor
by hand,

You *never* call a ctor by hand. There isn't even a way to do that in C++.
ctor's don't have names and thus aren't found during function call name lookup.

You always create an object and as a result of that the ctor is called. There
is a way in C++ to create an object in storage the program supplies (the method
is called 'placement new'), but even then it is: The program creates an object
and as a result of that the ctor gets called.
 
S

Sharad Kala

Ioannis Vranos said:
What is this? There is no guarantee for such a thing. Do you have TC++PL
3?

I think he is right.

5.3.4/8
A new-expression obtains storage for the object by calling an allocation
function (3.7.3.1). If the newexpression terminates by throwing an
exception, it may release storage by calling a deallocation function
(3.7.3.2). If the allocated type is a non-array type, the allocation
function's name is operator new and the deallocation function's name is
operator delete. If the allocated type is an array type, the allocation
function's name is operator new[] and the deallocation function's name is
operator delete[].


Sharad
 
S

Sharad Kala

Ioannis Vranos said:
What is the difference between operator new and new operator above? Are
you calling the user-defined one as "new operator"?

When you write code like this, MyClass *ps = new MyClass("abc"); the new you
are using is the new operator. It calls operator new in turn.

Sharad
 
M

Matthias =?ISO-8859-1?Q?K=E4ppler?=

Gianni said:
I suspect that Scott Meyers says you should never do this :

T * t = (T*) malloc( sizeof( T ) ); // C style dynamic allocation

The example above is how you would normally do in C what "new" does in
C++. You should allways use new/delete in C++.

Yes, but in how far is that different from just returning exactly this in an
overloaded operator 'new'? Does the compiler implicitly add some (for the
programmer invisible) code which can deal with the constructor call?
I'm referring to:

void * operator new( size_t size )
{
     return malloc( size );
}

This is as well just a call to malloc (I guess), hidden under the looks of
an operator 'new'. So why is the constructor called here?

- Matthias
 
S

Sharad Kala

Matthias Käppler said:
Yes, but in how far is that different from just returning exactly this in an
overloaded operator 'new'? Does the compiler implicitly add some (for the
programmer invisible) code which can deal with the constructor call?

Yes. Read Item 8 of Effective C++. I am copying a quote from the book -
<Quote>
Like malloc, operator new's only responsibility is to allocate memory. It
knows nothing about constructors. All operator new understands is memory
allocation. It is the job of the new operator to take the raw memory that
operator new returns and transform it into an object. When your compilers
see a statement like
string *ps = new string("Memory Management");
they must generate code that more or less corresponds to this (see Items E8
and E10, as well as the sidebar to my article on countingobjects, for a more
detailed treatment of this point):

void *memory = // get raw memory
operator new(sizeof(string)); // for a string
// object
call string::string("Memory Management") // initialize the
on *memory; // object in the
// memory
string *ps = // make ps point to
static_cast<string*>(memory); // the new object

HTH,
Sharad
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top