Passing address of stack memory to placement new operator

M

mangesh

This code is from c++ faq in section 11 :

void someCode()
{
char memory[sizeof(Fred)];
void* p = memory;
Fred* f = new(p) Fred();
f->~Fred(); // Explicitly call the destructor for the placed
object
}

Here we r passing address of stack memory to new .
New is used to allocate memory on heap . Then how can we pass address
of
stack memory to new operator . It is confusing .

Regards ,
Mangesh .
 
A

Alf P. Steinbach

* mangesh:
This code is from c++ faq in section 11 :

void someCode()
{
char memory[sizeof(Fred)];
void* p = memory;
Fred* f = new(p) Fred();

Should be

Fred* f = ::new(p) Fred();

f->~Fred(); // Explicitly call the destructor for the placed
object
}

Here we r passing address of stack memory to new .
New is used to allocate memory on heap . Then how can we pass address
of
stack memory to new operator . It is confusing .

The basic placement new operator (there are an infinity of them, but the
basic one from <new>) constructs an object in a specified region of memory.

You shouldn't use it because it's a low-level mechanism to subvert the
ordinary language rules and as such is fraught with dangers, even more
than with casts, e.g., as just one example, here that 'memory' may not
be properly aligned for an object of type 'Fred', and in particular:

* A novice should /never/ use the basic placement new.

Most uses of (the basic) placement new are better expressed using
standard library classes such as std::vector, which do the dangerous
stuff for you, in a safe way, so that you don't even see it.
 
L

Luke Meyers

mangesh said:
void someCode()
{
char memory[sizeof(Fred)];
void* p = memory;
Fred* f = new(p) Fred();
f->~Fred(); // Explicitly call the destructor for the placed
object
}

Here we r passing address of stack memory to new .

I find it baffling that you can take the time to place weird spaces
around your punctuation, but the three letters in the word "are" are
too much effort in the name of readability when you're asking others to
help you.

Anyway, yes, you're doing a placement-new on a stack-allocated array.
New is used to allocate memory on heap .

Not quite -- it allocates memory on the free store, which may or may
not be implemented in terms of the heap. It may also be overridden by
a custom allocator, which incidentally would likely make use of
placement new.
Then how can we pass address
of
stack memory to new operator . It is confusing .

Because a placement new doesn't allocate memory, it uses memory that
you've allocated for it. That's the entire point. It skips the
allocation step and goes straight to construction. It doesn't care
what part of memory the pointer points to, as long as it can be written
to.

Imagine, for example, implementing a custom allocator for small objects
based on a fixed-size arena allocated as a single chunk. That chunk
might be member data of an allocator class, and could therefore be
stack-allocated. Of course, if the allocator class was instantiated
dynamically, then its member data would live on the free store. Since
either could be the case, it would pose a real problem if the compiler
couldn't handle doing a placement new into stack-allocated memory.

Luke
 
M

mangesh

Hi ,
thanks for reply .
Now in given case is statement " f->~Fred() ; " really needed .
Since memory is on stack it will be automaticaly deleted on exiting
function .

Regards
Mangesh .



Luke said:
mangesh said:
void someCode()
{
char memory[sizeof(Fred)];
void* p = memory;
Fred* f = new(p) Fred();
f->~Fred(); // Explicitly call the destructor for the placed
object
}

Here we r passing address of stack memory to new .

I find it baffling that you can take the time to place weird spaces
around your punctuation, but the three letters in the word "are" are
too much effort in the name of readability when you're asking others to
help you.

Anyway, yes, you're doing a placement-new on a stack-allocated array.
New is used to allocate memory on heap .

Not quite -- it allocates memory on the free store, which may or may
not be implemented in terms of the heap. It may also be overridden by
a custom allocator, which incidentally would likely make use of
placement new.
Then how can we pass address
of
stack memory to new operator . It is confusing .

Because a placement new doesn't allocate memory, it uses memory that
you've allocated for it. That's the entire point. It skips the
allocation step and goes straight to construction. It doesn't care
what part of memory the pointer points to, as long as it can be written
to.

Imagine, for example, implementing a custom allocator for small objects
based on a fixed-size arena allocated as a single chunk. That chunk
might be member data of an allocator class, and could therefore be
stack-allocated. Of course, if the allocator class was instantiated
dynamically, then its member data would live on the free store. Since
either could be the case, it would pose a real problem if the compiler
couldn't handle doing a placement new into stack-allocated memory.

Luke
 
I

Ian Collins

mangesh said:
Hi ,
thanks for reply .
Now in given case is statement " f->~Fred() ; " really needed .
Since memory is on stack it will be automaticaly deleted on exiting
function .
Please don't top post.

The memory won't be deleted, it will no longer be usable so any object
created on the stack with placement new will be left in limbo.

That's one reason doing so is a daft idea.
 
R

Richard Herring

In message <[email protected]>,

Please don't top-post. I've moved your reply to where it should be.
Luke said:
mangesh said:
void someCode()
{
char memory[sizeof(Fred)];
void* p = memory;
Fred* f = new(p) Fred();
f->~Fred(); // Explicitly call the destructor for the placed
object
}
[big snip]
Hi ,
thanks for reply .
Now in given case is statement " f->~Fred() ; " really needed .
Yes.

Since memory is on stack it will be automaticaly deleted on exiting
function .

No. The memory will be deallocated, but the object's destructor is not
called unless you do so explicitly.

Allocating memory, constructing an object, destroying the object and
freeing the memory are four separate steps.
 
F

Frederick Gotham

mangesh posted:

char memory[sizeof(Fred)];


This array isn't necessarily suitably aligned. You need to make sure it's
suitably aligned by either:

(1) Dynamically allocating it
(2) Using union trickery
(3) Using boost's "align_for" (or whatever it's called)
 
A

Alf P. Steinbach

* Frederick Gotham:
Alf P. Steinbach posted:





Could you please explain that?

Unqualified placement new might invoke a custom Fred allocation function
instead of the basic placement new.
 
F

Frederick Gotham

Alf P. Steinbach posted:
* Frederick Gotham:

Unqualified placement new might invoke a custom Fred allocation function
instead of the basic placement new.


When you want to use "placement new", would it be wise to always use:


::new(p) Type();


(I realise it won't make a difference with intrinsic types, but it's
consistent nonetheless for dealing with class types).
 
M

mlimber

Alf said:
* Frederick Gotham:

Unqualified placement new might invoke a custom Fred allocation function
instead of the basic placement new.

But if there is a custom placement new operator defined for Fred,
presumably it is meant to be used. Leaving it unqualified seems fine to
me.

Cheers! --M
 
A

Alf P. Steinbach

* Frederick Gotham:
Alf P. Steinbach posted:


When you want to use "placement new", would it be wise to always use:

::new(p) Type();

(I realise it won't make a difference with intrinsic types, but it's
consistent nonetheless for dealing with class types).

Yes, that's good advice when you want the in-place construction
behavior, not a custom allocator: let's update FAQ item [11.10]... ;-)

CC: Marshall Cline
 
A

Alf P. Steinbach

* mlimber:
But if there is a custom placement new operator defined for Fred,
presumably it is meant to be used.

Depends what you want. If you want to leave the decision of how to
allocate the memory to class Fred, use 'new'. If you want to take
charge, saying Here Should Be Placement Construction, use '::new'.

Leaving it unqualified seems fine to me.

If you want to leave the choice of allocation scheme to class Fred, yes,
but given that you've declared a buffer to put the object in, how likely
is that?
 
M

mlimber

Alf said:
* mlimber:

Depends what you want. If you want to leave the decision of how to
allocate the memory to class Fred, use 'new'. If you want to take
charge, saying Here Should Be Placement Construction, use '::new'.

In either case, we're using placement new and allocation is done
outside the new operator itself. (If the custom placement new does
something different, it has changed the semantics of that operator and
is no different than changing the semantics of other overloaded
operators, which is generally considered evil as in FAQ 13.9.)
If you want to leave the choice of allocation scheme to class Fred, yes,
but given that you've declared a buffer to put the object in, how likely
is that?

By the same logic I think we could justly say that if we've overridden
the placement new operator for this class, how likely is it that we
want to use the global one? Also, Sutter and Alexandrescu note, "If a
class defines any overload of operator new, it should provide overloads
of all three of plain, in-place, and non-throwing operator new. If you
don't, they'll be hidden and unavailable to users of your class." (_C++
Coding Standards_, Item 46).

Cheers! --M
 
A

Alf P. Steinbach

* mlimber:
In either case, we're using placement new and allocation is done
outside the new operator itself.
Yes.


(If the custom placement new does
something different, it has changed the semantics of that operator

No (it's a circular argument: assuming that 'new' invokes some standard
semantics for the allocation function, then arguing that if it doesn't
the semantics have been changed, but the only standard semantics is for
'::new').

and
is no different than changing the semantics of other overloaded
operators, which is generally considered evil as in FAQ 13.9.)
Yes.



By the same logic I think we could justly say that if we've overridden
the placement new operator for this class,
No.


how likely is it that we want to use the global one?

Very. E.g., consider implementing something like a std::vector. Should
a std::vector<Fred> use Fred's placement allocation function if one is
defined? With MSVC 7.1 it does. With g++ 3.4.4 it doesn't. When that
function is inaccessible the code doesn't compile with MSVC 7.1, and I
don't see accessibility of that function as a requirement for standard
container elements (so I think that compiler is wrong). With g++ 3.4.4
the code compiles (which I think is correct, and anyway, it is IMO how a
properly designed & implemented class should work, no surprises).

Also, Sutter and Alexandrescu note, "If a
class defines any overload of operator new, it should provide overloads
of all three of plain, in-place, and non-throwing operator new. If you
don't, they'll be hidden and unavailable to users of your class." (_C++
Coding Standards_, Item 46).

Yes.

However, blaming the designer of class Fred is just that, assigning
blame: instead one should IMO make sure that there is no blame to
assign, by the simple expedient of using code that does what one wants
regardless of the class in question.
 
M

mlimber

Alf said:
* mlimber:
In either case, we're using placement new and allocation is done
outside the new operator itself. [snip]
(If the custom placement new does
something different, it has changed the semantics of that operator

No (it's a circular argument: assuming that 'new' invokes some standard
semantics for the allocation function, then arguing that if it doesn't
the semantics have been changed, but the only standard semantics is for
'::new').

I don't follow you here. Please clarify.

No what? I hadn't even finished my thought yet! :p
Very. E.g., consider implementing something like a std::vector. Should
a std::vector<Fred> use Fred's placement allocation function if one is
defined? With MSVC 7.1 it does. With g++ 3.4.4 it doesn't. When that
function is inaccessible the code doesn't compile with MSVC 7.1, and I
don't see accessibility of that function as a requirement for standard
container elements (so I think that compiler is wrong). With g++ 3.4.4
the code compiles (which I think is correct, and anyway, it is IMO how a
properly designed & implemented class should work, no surprises).

Sutter and Alexandrescu do note in the same item cited previously that
"you should always avoid hiding in-place new because STL containers use
it extensively." However, it seems to me that this is more of a
quality-of-implementation issue (since having the STL use in-place new
is not required by the standard, right?) or a defect in the standard
(the STL containers should have that requirement).

Cheers! --M
 

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,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top