Custom STL in place allocator crashed

Discussion in 'C++' started by Allen, Dec 31, 2008.

  1. Allen

    Allen Guest

    There is a custom STL in place allocator in Google codes.
    The InPlaceAlloc.h URL is
    http://www.google.com/codesearch/p?hl=en#HClD5fLW7P8/InPlaceAlloc.h&q=InPlaceAlloc.h

    #include <vector>
    #include "InPlaceAlloc.h"

    int main()
    {
    char * buffer = new char[1024];
    typedef InPlaceAlloc<int> IPA;
    std::vector<int, IPA> v(IPA(buffer, 1024));

    // insert elements
    // - causes reallocations
    v.push_back(42);
    v.push_back(56);
    v.push_back(11);
    v.push_back(22);
    v.push_back(33);
    v.push_back(44);

    delete[] buffer;
    buffer = NULL;
    }

    Run the program in MSVC8, it will crash.

    Why? Please help me. Thank you.

    Allen
    Allen, Dec 31, 2008
    #1
    1. Advertising

  2. Allen

    red floyd Guest

    Allen wrote:
    > There is a custom STL in place allocator in Google codes.
    > The InPlaceAlloc.h URL is
    > http://www.google.com/codesearch/p?hl=en#HClD5fLW7P8/InPlaceAlloc.h&q=InPlaceAlloc.h
    >
    > #include <vector>
    > #include "InPlaceAlloc.h"
    >
    > int main()
    > {
    > char * buffer = new char[1024];
    > typedef InPlaceAlloc<int> IPA;
    > std::vector<int, IPA> v(IPA(buffer, 1024));
    >
    > // insert elements
    > // - causes reallocations
    > v.push_back(42);
    > v.push_back(56);
    > v.push_back(11);
    > v.push_back(22);
    > v.push_back(33);
    > v.push_back(44);
    >
    > delete[] buffer;
    > buffer = NULL;

    At this point, v's destructor has yet to run.
    > }
    >
    > Run the program in MSVC8, it will crash.
    >
    > Why? Please help me. Thank you.
    >
    red floyd, Dec 31, 2008
    #2
    1. Advertising

  3. Allen

    Allen Guest

    On 12ÔÂ31ÈÕ, ÉÏÎç9ʱ14·Ö, Allen <Allen.Che...@gmail..com> wrote:
    > There is a custom STL in place allocator in Google codes.
    > The InPlaceAlloc.h URL ishttp://www.google.com/codesearch/p?hl=en#HClD5fLW7P8/InPlaceAlloc.h&q...
    >
    > #include <vector>
    > #include "InPlaceAlloc.h"
    >
    > int main()
    > {
    > char * buffer = new char[1024];
    > typedef InPlaceAlloc<int> IPA;
    > std::vector<int, IPA> v(IPA(buffer, 1024));


    It crashs at above line.

    >
    > // insert elements
    > // - causes reallocations
    > v.push_back(42);
    > v.push_back(56);
    > v.push_back(11);
    > v.push_back(22);
    > v.push_back(33);
    > v.push_back(44);
    >
    > delete[] buffer;
    > buffer = NULL;
    >
    > }
    >
    > Run the program in MSVC8, it will crash.
    >
    > Why? Please help me. Thank you.
    >
    > Allen
    Allen, Dec 31, 2008
    #3
  4. Allen schrieb:
    > On 12ÔÂ31ÈÕ, ÉÏÎç9ʱ14·Ö, Allen <> wrote:
    >> There is a custom STL in place allocator in Google codes.
    >> The InPlaceAlloc.h URL ishttp://www.google.com/codesearch/p?hl=en#HClD5fLW7P8/InPlaceAlloc.h&q...
    >>
    >> #include <vector>
    >> #include "InPlaceAlloc.h"
    >>
    >> int main()
    >> {
    >> char * buffer = new char[1024];


    Avoid new[]. Avoid delete[]. Except buried down in a class or library.
    You can use std::vector to allocate a buffer:

    std::vector<char> buffer(1024);

    >> typedef InPlaceAlloc<int> IPA;
    >> std::vector<int, IPA> v(IPA(buffer, 1024));


    std::vector<int, IPA> v(IPA(&buffer[0], buffer.size()));

    > It crashs at above line.


    It crashs, because InPlaceAlloc is broken. The copy constructor and the
    assignment operator are defined but empty with a comment saying "do
    nothing". That won't work.

    --
    Thomas
    Thomas J. Gritzan, Dec 31, 2008
    #4
  5. Allen

    tni Guest

    Allen wrote:
    > There is a custom STL in place allocator in Google codes.
    > The InPlaceAlloc.h URL is
    > http://www.google.com/codesearch/p?hl=en#HClD5fLW7P8/InPlaceAlloc.h&q=InPlaceAlloc.h
    >
    > #include <vector>
    > #include "InPlaceAlloc.h"
    >
    > int main()
    > {
    > char * buffer = new char[1024];
    > typedef InPlaceAlloc<int> IPA;
    > std::vector<int, IPA> v(IPA(buffer, 1024));



    You do realize that you are using an int vector with a char sized
    buffer, right?

    It should be:
    char * buffer = new char[1024 * sizeof(int)];
    tni, Dec 31, 2008
    #5
  6. Allen

    zr Guest

    On Dec 31, 4:20 am, "Thomas J. Gritzan" <>
    wrote:
    > Allen schrieb:
    >
    > > On 12ÔÂ31ÈÕ, ÉÏÎç9ʱ14·Ö, Allen <> wrote:
    > >> There is a custom STL in place allocator in Google codes.
    > >> The InPlaceAlloc.h URL ishttp://www.google.com/codesearch/p?hl=en#HClD5fLW7P8/InPlaceAlloc.h&q...

    >
    > >> #include <vector>
    > >> #include "InPlaceAlloc.h"

    >
    > >> int main()
    > >> {
    > >> char * buffer = new char[1024];

    >
    > Avoid new[]. Avoid delete[]. Except buried down in a class or library.
    > You can use std::vector to allocate a buffer:
    >
    > std::vector<char> buffer(1024);
    >

    Why is using a vector to allocate better than using new[] and delete
    []?
    zr, Dec 31, 2008
    #6
  7. zr wrote:
    > Why is using a vector to allocate better than using new[] and delete
    > []?


    Because a std::vector is scoped, which means that when it goes out of
    scope, it will delete the array automatically, thus lessening the
    chances of a memory leak (especially inside functions which may have
    surprising exit points).

    Basically std::vector is an encapsulated way of dynamically allocating
    an array.

    When you write a 'new' and use the raw pointer, you always risk a
    memory leak if you are not very careful.
    Juha Nieminen, Dec 31, 2008
    #7
  8. zr schrieb:
    > On Dec 31, 4:20 am, "Thomas J. Gritzan" <>
    > wrote:
    >> Allen schrieb:
    >>
    >>> On 12ÔÂ31ÈÕ, ÉÏÎç9ʱ14·Ö, Allen <> wrote:
    >>>> There is a custom STL in place allocator in Google codes.
    >>>> The InPlaceAlloc.h URL ishttp://www.google.com/codesearch/p?hl=en#HClD5fLW7P8/InPlaceAlloc.h&q...
    >>>> #include <vector>
    >>>> #include "InPlaceAlloc.h"
    >>>> int main()
    >>>> {
    >>>> char * buffer = new char[1024];

    >> Avoid new[]. Avoid delete[]. Except buried down in a class or library.
    >> You can use std::vector to allocate a buffer:
    >>
    >> std::vector<char> buffer(1024);
    >>

    > Why is using a vector to allocate better than using new[] and delete
    > []?


    In general, because it lessens the risk of memory leaks.
    With new[], you have to delete[] in every possible code path, which can
    be quite complicated in some functions, especially if you allocate
    multiple arrays.
    It is very hard to make it exception safe. Most people don't even try it
    and ignore that issue. With std::vector or any other smart-pointer or
    RAII construct, the objects will be destroyed even then.

    In this special case, the buffer is used by the other std::vector and
    its allocator. The code delete[]s the buffer to early while it is still
    in use. But destructors run in reverse order to its constructor calls,
    so if you use std::vector in this case, the buffer won't be deallocated
    until the vector that uses this buffer is alive.

    --
    Thomas
    Thomas J. Gritzan, Dec 31, 2008
    #8
  9. Allen

    James Kanze Guest

    On Dec 31 2008, 4:04 pm, Pete Becker <> wrote:
    > On 2008-12-31 09:37:54 -0500, zr <> said:
    > > On Dec 31, 4:20 am, "Thomas J. Gritzan" <>
    > > wrote:
    > >> Allen schrieb:


    > >>> On 12月31æ—¥, 上åˆ9æ—¶14分, Allen <Allen.Che...@g

    > > mail.com> wrote:
    > >>>> There is a custom STL in place allocator in Google codes.
    > >>>> The InPlaceAlloc.h URL ishttp://www.google.com/codesearch/p?hl=en#HC

    > > lD5fLW7P8/InPlaceAlloc.h&q...


    > >>>> #include <vector>
    > >>>> #include "InPlaceAlloc.h"


    > >>>> int main()
    > >>>> {
    > >>>> char * buffer = new char[1024];


    > >> Avoid new[]. Avoid delete[]. Except buried down in a class or library.
    > >> You can use std::vector to allocate a buffer:


    > >> std::vector<char> buffer(1024);


    > > Why is using a vector to allocate better than using new[] and delete
    > > []?


    > Orthodoxy.


    In the usual case where the lifetime is scoped, it's the
    simplest way to ensure exception safety, and definitly to be
    prefered. Any time the array is to be passed as a parameter, it
    acts like a real type, with value semantics and no special ad
    hoc rules about converting to a pointer to the first element,
    and it carries its size around with it as well. Most
    implementations will also bounds check, which is really, really
    rare for built in arrays. (I think I've only heard of one
    compiler which bounds checks built-in arrays, and I don't know
    if it is even still around.)

    In 20 years of programming C++, I've never used an operator
    new[]. (I do still use C style arrays in certain cases, but
    never dynamically allocated.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jan 1, 2009
    #9
  10. Allen

    James Kanze Guest

    On Dec 31 2008, 8:42 pm, "Thomas J. Gritzan" <>
    wrote:
    > zr schrieb:
    > > On Dec 31, 4:20 am, "Thomas J. Gritzan" <>
    > > wrote:
    > >> Allen schrieb:


    > >>> On 12月31æ—¥, 上åˆ9æ—¶14分, Allen <> wrote:
    > >>>> There is a custom STL in place allocator in Google codes.
    > >>>> The InPlaceAlloc.h URL ishttp://www.google.com/codesearch/p?hl=en#HClD5fLW7P8/InPlaceAlloc.h&q...
    > >>>> #include <vector>
    > >>>> #include "InPlaceAlloc.h"
    > >>>> int main()
    > >>>> {
    > >>>> char * buffer = new char[1024];
    > >> Avoid new[]. Avoid delete[]. Except buried down in a class or library.
    > >> You can use std::vector to allocate a buffer:


    > >> std::vector<char> buffer(1024);


    > > Why is using a vector to allocate better than using new[]
    > > and delete []?


    > In general, because it lessens the risk of memory leaks. With
    > new[], you have to delete[] in every possible code path, which
    > can be quite complicated in some functions, especially if you
    > allocate multiple arrays. It is very hard to make it
    > exception safe. Most people don't even try it and ignore that
    > issue. With std::vector or any other smart-pointer or RAII
    > construct, the objects will be destroyed even then.


    That's true, but not really relevant here. Similarly, a much
    more important reason for using std::vector is that in any
    decent implementation, the operator[] will be bounds checked,
    and the type in general behaves like a normal type, with value
    semantics. And that the type carries its dimensions along with
    it.

    None of which are really relevant here, because the user isn't
    allocating an array, in the classical sense, he's allocating raw
    memory. And the problem with new char[] is that it says the
    wrong thing; it says that he is allocating an array of char. I
    know, the language allows an array of char to be used as raw
    memory. But that doesn't mean that you can't write code which
    says what you mean. In this case, I'd call the ::eek:perator new
    function directly, e.g.:

    void* buffer = ::eek:perator new( quantityNeeded ) ;
    // ...
    ::eek:perator delete( buffer ) ;

    (I'd also maintain the pointer as a void* where ever possible,
    since this is the conventional type for a pointer to raw
    memory.)

    With regards to his original code:

    1. I'd also ensure that the allocator took not only a pointer,
    but also the size, and verify that constantly. (Part of his
    problem, at least, is that the array he's allocating isn't
    big enough.)

    2. I'd define some memory management strategy. The simplest,
    here, is just to use the Boehm collector; another solution
    I've found useful in many cases is to pass an additional
    boolean argument to the client, telling it whether to delete
    in the destructor or not---since allocator must support
    copy, this would require some tricky reference counting
    here. Or... Just a guess, but it wouldn't surprise me if in
    all of the actual use cases for this class, the memory
    doesn't really have to be deleted anyway. (But if he'd
    posted code without the delete, a lot of people would have
    screamed about that.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jan 1, 2009
    #10
  11. Allen

    James Kanze Guest

    On Jan 1, 1:04 pm, Pete Becker <> wrote:
    > On 2009-01-01 06:16:07 -0500, James Kanze <> said:
    > > On Dec 31 2008, 4:04 pm, Pete Becker <> wrote:
    > >> On 2008-12-31 09:37:54 -0500, zr <> said:
    > >>> On Dec 31, 4:20 am, "Thomas J. Gritzan" <>
    > >>> wrote:
    > >>>> Allen schrieb:
    > >>>>>> #include <vector>
    > >>>>>> #include "InPlaceAlloc.h"


    > >>>>>> int main()
    > >>>>>> {
    > >>>>>> char * buffer = new char[1024];


    > >>>> Avoid new[]. Avoid delete[]. Except buried down in a
    > >>>> class or library. You can use std::vector to allocate a
    > >>>> buffer:


    > >>>> std::vector<char> buffer(1024);


    > >>> Why is using a vector to allocate better than using new[]
    > >>> and delete[]?


    > >> Orthodoxy.


    > > In the usual case where the lifetime is scoped, it's the
    > > simplest way to ensure exception safety, and definitly to be
    > > prefered.


    > In the example code, it had nothing to do with the problem.


    Yes. I only saw the complete example later; in this particular
    case (allocating raw memory), I wouldn't recommend std::vector,
    at least not systematically. But in this case, I'd prefer that
    the statement make it clear that I was allocating raw memory,
    i.e.:
    void* buffer = ::eek:perator new( requiredSize ) ;
    It's just a coding convention, but I find it a clear way to say:
    attention: this is raw memory, and not an array of characters.

    > But I guess there's a difference in viewpoint here. I think
    > it's important to try to give a clear answer to the question
    > that was asked. Others like to pontificate on how the sample
    > code didn't meet their coding guidelines, with so much
    > lecturing that the answer to the question gets lost. Oddly
    > enough, the original problem no longer appears in the quoted
    > text.


    Exactly. Which is why I reacted to your response: in almost all
    cases, std::vector is preferable. This just happens to be an
    exception.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jan 2, 2009
    #11
    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. Dan
    Replies:
    0
    Views:
    456
  2. =?ISO-8859-1?Q?Ralf_Schneewei=DF?=

    How to write an allocator for the STL List in VC++ 6.0

    =?ISO-8859-1?Q?Ralf_Schneewei=DF?=, Aug 20, 2003, in forum: C++
    Replies:
    2
    Views:
    597
    Shane Beasley
    Aug 21, 2003
  3. Brian Genisio
    Replies:
    12
    Views:
    7,962
    tom_usenet
    Jan 15, 2004
  4. Scott Brady Drummonds

    STL v. Norma" Memory Allocator

    Scott Brady Drummonds, Jan 30, 2004, in forum: C++
    Replies:
    5
    Views:
    689
    tom_usenet
    Feb 2, 2004
  5. Dave Rahardja

    STL custom allocator design

    Dave Rahardja, Jan 31, 2007, in forum: C++
    Replies:
    4
    Views:
    481
    Dave Rahardja
    Feb 1, 2007
Loading...

Share This Page