Passing address of stack memory to placement new operator

Discussion in 'C++' started by mangesh, Jun 30, 2006.

  1. mangesh

    mangesh Guest

    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 .
    mangesh, Jun 30, 2006
    #1
    1. Advertising

  2. * 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.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Jun 30, 2006
    #2
    1. Advertising

  3. mangesh

    Luke Meyers Guest

    mangesh wrote:
    > 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
    Luke Meyers, Jun 30, 2006
    #3
  4. mangesh

    mangesh Guest

    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 Meyers wrote:
    > mangesh wrote:
    > > 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
    mangesh, Jun 30, 2006
    #4
  5. mangesh

    Ian Collins Guest

    mangesh wrote:
    > 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.

    --
    Ian Collins.
    Ian Collins, Jun 30, 2006
    #5
  6. In message <>,
    mangesh <> writes

    Please don't top-post. I've moved your reply to where it should be.

    >
    >Luke Meyers wrote:
    >> mangesh wrote:
    >> > 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.

    --
    Richard Herring
    Richard Herring, Jun 30, 2006
    #6
  7. Alf P. Steinbach posted:


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

    >
    > Should be
    >
    > Fred* f = ::new(p) Fred();




    Could you please explain that?


    --

    Frederick Gotham
    Frederick Gotham, Jun 30, 2006
    #7
  8. 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)


    --

    Frederick Gotham
    Frederick Gotham, Jun 30, 2006
    #8
  9. * Frederick Gotham:
    > Alf P. Steinbach posted:
    >
    >
    >>> Fred* f = new(p) Fred();

    >> Should be
    >>
    >> Fred* f = ::new(p) Fred();

    >
    >
    >
    > Could you please explain that?


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

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Jun 30, 2006
    #9
  10. Alf P. Steinbach posted:

    > * Frederick Gotham:
    >> Alf P. Steinbach posted:
    >>
    >>
    >>>> Fred* f = new(p) Fred();
    >>> Should be
    >>>
    >>> Fred* f = ::new(p) Fred();

    >>
    >>
    >>
    >> Could you please explain that?

    >
    > 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).

    --

    Frederick Gotham
    Frederick Gotham, Jun 30, 2006
    #10
  11. mangesh

    mlimber Guest

    Alf P. Steinbach wrote:
    > * Frederick Gotham:
    > > Alf P. Steinbach posted:
    > >>> Fred* f = new(p) Fred();
    > >> Should be
    > >>
    > >> Fred* f = ::new(p) Fred();

    > >
    > > Could you please explain that?

    >
    > 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
    mlimber, Jun 30, 2006
    #11
  12. * Frederick Gotham:
    > Alf P. Steinbach posted:
    >
    >> * Frederick Gotham:
    >>> Alf P. Steinbach posted:
    >>>
    >>>
    >>>>> Fred* f = new(p) Fred();
    >>>> Should be
    >>>>
    >>>> Fred* f = ::new(p) Fred();
    >>>
    >>>
    >>> Could you please explain that?

    >> 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).


    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: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Jun 30, 2006
    #12
  13. * mlimber:
    > Alf P. Steinbach wrote:
    >> * Frederick Gotham:
    >>> Alf P. Steinbach posted:
    >>>>> Fred* f = new(p) Fred();
    >>>> Should be
    >>>>
    >>>> Fred* f = ::new(p) Fred();
    >>> Could you please explain that?

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


    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?

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Jun 30, 2006
    #13
  14. mangesh

    mlimber Guest

    Alf P. Steinbach wrote:
    > * mlimber:
    > > Alf P. Steinbach wrote:
    > >> * Frederick Gotham:
    > >>> Alf P. Steinbach posted:
    > >>>>> Fred* f = new(p) Fred();
    > >>>> Should be
    > >>>>
    > >>>> Fred* f = ::new(p) Fred();
    > >>> Could you please explain that?
    > >> 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.

    >
    > 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.)

    > > 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?


    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
    mlimber, Jun 30, 2006
    #14
  15. * mlimber:
    > Alf P. Steinbach wrote:
    >> * mlimber:
    >>> Alf P. Steinbach wrote:
    >>>> * Frederick Gotham:
    >>>>> Alf P. Steinbach posted:
    >>>>>>> Fred* f = new(p) Fred();
    >>>>>> Should be
    >>>>>>
    >>>>>> Fred* f = ::new(p) Fred();
    >>>>> Could you please explain that?
    >>>> 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.

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


    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.


    >>> 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?

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

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Jun 30, 2006
    #15
  16. mangesh

    mlimber Guest

    Alf P. Steinbach wrote:
    > * 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.

    > >>> 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?

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

    >
    > No.


    No what? I hadn't even finished my thought yet! :p

    > > 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).


    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
    mlimber, Jun 30, 2006
    #16
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ioannis Vranos

    Placement operator new/delete question

    Ioannis Vranos, Oct 16, 2004, in forum: C++
    Replies:
    11
    Views:
    5,676
    Ioannis Vranos
    Oct 16, 2004
  2. Mark P
    Replies:
    6
    Views:
    805
    James Dennett
    Apr 27, 2005
  3. Replies:
    13
    Views:
    898
    Alf P. Steinbach
    Jul 7, 2006
  4. Lagarde Sébastien

    overriding placement new + memory management

    Lagarde Sébastien, May 4, 2007, in forum: C++
    Replies:
    5
    Views:
    543
    Lagarde Sébastien
    May 7, 2007
  5. xmllmx
    Replies:
    6
    Views:
    414
    xmllmx
    Feb 3, 2010
Loading...

Share This Page