Dynamically allocated array question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jeff Williams

    Dynamically allocated array question

    Ok, everyone loves to talk about dynamic arrays and ptr's etc, they provide
    endless conversation :) so here goes:

    Will this leak memory (my intuition says yes):

    void foo(vector<int* >& vec)
    {
    int* pInts = new int[100];
    for(int i = 0; i < 100; i++)
    vec.push_back(p Ints[i]);
    }

    // It can be assumed that later on in the program vec will have
    // delete called on each individual element

    This example is to simulate a technique I am using involving more
    complicated stuff so yes I realize there are better ways to do the above in
    this simple case.

    But also I will explain what I am trying to do in the bigger picture in case
    anyone wishes to make suggestions.

    I want to fill a container (a vector but it shouldnt matter what) with ptr's
    to instances of objects. But there will be millions of these objects and I
    wish to allocate them all at once and add them to the container. The
    calling code doesn't really know the exact type of the object that will go
    into the container, it only knows they will at least derive off the type of
    the ptr in the container. BUT in reality they will all be the same object,
    which is why i want to allocate them all at once... for speed and to avoid
    fragmenting memory.

    So the obvious solution of something like:

    vector<basePtr* > vec;
    vec.reserve(100 0000);
    for(int i = 0; i < 1000000; ++i)
    {
    basePtr* pOb = CreateObject(); // virtual func
    vec.push_back(p Ob);
    }

    isn't the solution I want

    Jeff


  • Alf P. Steinbach

    #2
    Re: Dynamically allocated array question

    On Mon, 18 Aug 2003 16:30:34 GMT, "Jeff Williams" <no_spam_remove _up_to_here_jwi lliams@mfchelp. com> wrote:
    [color=blue]
    >Ok, everyone loves to talk about dynamic arrays and ptr's etc, they provide
    >endless conversation :) so here goes:
    >
    >Will this leak memory (my intuition says yes):
    >
    >void foo(vector<int* >& vec)
    >{
    > int* pInts = new int[100];
    > for(int i = 0; i < 100; i++)
    > vec.push_back(p Ints[i]);
    >}[/color]

    You don't need intutition for that: there is an allocation, no
    corresponding deallocation, and the pointer value is lost on exit
    from the function so there can not be later deallocation either.


    [color=blue]
    >// It can be assumed that later on in the program vec will have
    >// delete called on each individual element[/color]

    In that case each element must be allocated via 'new'.


    [color=blue]
    >I want to fill a container (a vector but it shouldnt matter what) with ptr's
    >to instances of objects. But there will be millions of these objects and I
    >wish to allocate them all at once and add them to the container.[/color]

    std::vector<Sma llObject> smallObjectCach e( cacheSize );

    Also/alternatively check up on the fly-weight pattern, if you haven't.

    Comment

    • Dimitris Kamenopoulos

      #3
      Re: Dynamically allocated array question

      Jeff Williams wrote:
      [color=blue]
      > Ok, everyone loves to talk about dynamic arrays and ptr's etc, they
      > provide endless conversation :) so here goes:
      >
      > Will this leak memory (my intuition says yes):
      >
      > void foo(vector<int* >& vec)
      > {
      > int* pInts = new int[100];
      > for(int i = 0; i < 100; i++)
      > vec.push_back(p Ints[i]);
      > }
      >
      > // It can be assumed that later on in the program vec will have
      > // delete called on each individual element[/color]

      Actually it cannot be assumed. And even if vec *did* call delete,
      "delete"ing every element of a dynamically allocated array is definitely an
      error. You must invoke delete[] on pInts, no two ways about it.
      [color=blue]
      > This example is to simulate a technique I am using involving more
      > complicated stuff so yes I realize there are better ways to do the above
      > in this simple case.
      >
      > But also I will explain what I am trying to do in the bigger picture in
      > case anyone wishes to make suggestions.
      >
      > I want to fill a container (a vector but it shouldnt matter what) with
      > ptr's
      > to instances of objects. But there will be millions of these objects and
      > I
      > wish to allocate them all at once and add them to the container. The
      > calling code doesn't really know the exact type of the object that will go
      > into the container, it only knows they will at least derive off the type
      > of
      > the ptr in the container. BUT in reality they will all be the same
      > object, which is why i want to allocate them all at once... for speed and
      > to avoid fragmenting memory.[/color]

      Sorry, I don't understand what you 're trying to do :-(

      Comment

      • Dimitris Kamenopoulos

        #4
        Re: Dynamically allocated array question

        Dimitris Kamenopoulos wrote:

        [color=blue][color=green]
        >> void foo(vector<int* >& vec)
        >> {
        >> int* pInts = new int[100];
        >> for(int i = 0; i < 100; i++)
        >> vec.push_back(p Ints[i]);
        >> }
        >>
        >> // It can be assumed that later on in the program vec will have
        >> // delete called on each individual element[/color]
        >
        > Actually it cannot be assumed. And even if vec *did* call delete,
        > "delete"ing every element of a dynamically allocated array is definitely
        > an error. You must invoke delete[] on pInts, no two ways about it.[/color]

        Furthermore, what you would get in the vector if your example compiled (IOW
        if vec was vector<int>) is a copy of every int stored in pInts, the
        "contents" of pInts[*] themselves live happily ever after and, of course,
        are leaked.
        [*] more accurately, the contents of the memory pointed to by pInts.

        Comment

        • Andrey Tarasevich

          #5
          Re: Dynamically allocated array question

          Jeff Williams wrote:[color=blue]
          > ...
          > Will this leak memory (my intuition says yes):
          >
          > void foo(vector<int* >& vec)
          > {
          > int* pInts = new int[100];
          > for(int i = 0; i < 100; i++)
          > vec.push_back(p Ints[i]);
          > }[/color]

          The code makes no sense. Your vector stores values of type 'int*' and
          you are pushing values of type 'int' into it. Please, always try posting
          real (or at least compilable) code.

          You probably meant something like

          vec.push_back(& pInts[i]);

          or

          vec.push_back(p Ints + i);
          [color=blue]
          > // It can be assumed that later on in the program vec will have
          > // delete called on each individual element[/color]

          You can't call 'delete' on each individual element in this case. What
          you can do is to call 'delete[]' on all elements at once:

          delete[] vec.front();

          --
          Best regards,
          Andrey Tarasevich
          Brainbench C and C++ Programming MVP

          Comment

          • Jeff Williams

            #6
            Re: Dynamically allocated array question

            Yes my example code was in error, let me post the correct version and clean
            up my question a little:

            new example code:

            struct base_class { };
            struct derive_class : base_class { };

            void foo(std::vector <base_class*> & vec)
            {
            base_class* pBases = new derive_class[100];
            for(int i = 0; i < 100; ++i)
            vec.push_back(& pBases[i]);
            }

            void bar(std::vector <base_class*> & vec)
            {
            for(int i = 0; i < vec.size(); ++i)
            delete vec[i];
            vec.clear();
            }

            // I dont give a crap that the main func has bad prototype so dont even
            bother
            int main()
            {
            std::vector<bas e_class*> vec;
            foo(vec);
            bar(vec);
            return 0;
            }


            Now, with this example only, is memory leaked? My intuition says yes
            because I allocated with new[] but didnt de-allocate with delete[], so
            somewhere the compiler must have stored the size of the array but it never
            cleaned that up.

            And just forget about the latter part of my original question, I didn't
            provide enough context to make it clear and doing so would require more time
            and space than most would care to read I believe.

            Jeff


            "Kevin Goodsell" <usenet1.spamfr ee.fusion@never box.com> wrote in message
            news:3f415089@s hknews01...[color=blue]
            > Jeff Williams wrote:
            >[color=green]
            > > Ok, everyone loves to talk about dynamic arrays and ptr's etc, they[/color][/color]
            provide[color=blue][color=green]
            > > endless conversation :) so here goes:
            > >
            > > Will this leak memory (my intuition says yes):[/color]
            >
            > As far as I can tell, it will not. But only because it won't compile.
            >[color=green]
            > >
            > > void foo(vector<int* >& vec)
            > > {
            > > int* pInts = new int[100];
            > > for(int i = 0; i < 100; i++)
            > > vec.push_back(p Ints[i]);
            > > }[/color]
            >
            > vec holds int pointers. pInts[i] is an int. Implicit conversion from int
            > to int * is not allowed.
            >[color=green]
            > >
            > > // It can be assumed that later on in the program vec will have
            > > // delete called on each individual element[/color]
            >
            > That would create an error, since each individual element is *not* a
            > pointer to something that was allocated with 'new'. You don't get to
            > make up the rules for how 'new' and 'delete' are used. They are:
            > Anything that is created with 'new' must eventually be destroyed by
            > applying 'delete' to it exactly once. Anything that is created with
            > 'new[]' must eventually be destroyed by applying 'delete[]' to it
            > exactly once.
            >[color=green]
            > >
            > > This example is to simulate a technique I am using involving more
            > > complicated stuff so yes I realize there are better ways to do the above[/color][/color]
            in[color=blue][color=green]
            > > this simple case.
            > >
            > > But also I will explain what I am trying to do in the bigger picture in[/color][/color]
            case[color=blue][color=green]
            > > anyone wishes to make suggestions.
            > >
            > > I want to fill a container (a vector but it shouldnt matter what) with[/color][/color]
            ptr's[color=blue][color=green]
            > > to instances of objects. But there will be millions of these objects[/color][/color]
            and I[color=blue][color=green]
            > > wish to allocate them all at once and add them to the container. The
            > > calling code doesn't really know the exact type of the object that will[/color][/color]
            go[color=blue][color=green]
            > > into the container, it only knows they will at least derive off the type[/color][/color]
            of[color=blue][color=green]
            > > the ptr in the container. BUT in reality they will all be the same[/color][/color]
            object,[color=blue][color=green]
            > > which is why i want to allocate them all at once... for speed and to[/color][/color]
            avoid[color=blue][color=green]
            > > fragmenting memory.[/color]
            >
            > That's fine, but possibly misguided. Are you sure allocating all at once
            > will speed it up enough to be worth the effort? Also, what if you can't
            > get a single, huge chunk of memory large enough to hold all of the
            > objects, but you *can* get 2 or 3 smaller chunks that together are large
            > enough?
            >[color=green]
            > >
            > > So the obvious solution of something like:
            > >
            > > vector<basePtr* > vec;
            > > vec.reserve(100 0000);
            > > for(int i = 0; i < 1000000; ++i)
            > > {
            > > basePtr* pOb = CreateObject(); // virtual func
            > > vec.push_back(p Ob);[/color]
            >
            > What's wrong with
            >
            > vec.push_back(C reateObject());
            >
            > ?
            >[color=green]
            > > }
            > >
            > > isn't the solution I want[/color]
            >
            > Why not? It looks fine to me (except for the part about CreateObject
            > being virtual). CreateObject could simply return the next available
            > object in your massive allocation.
            >
            > In fact, you could make it a bit better by doing something like this:
            >
            > class Cache
            > {
            > public:
            > Cache() : p(new SomeObject[1000000]) {}
            > SomeBase *CreateObject() ;
            > void ReleaseObject(S omeBase *);
            > ~Cache() { delete [] p; }
            >
            > private:
            > SomeBase *p;
            > };
            >
            > It needs work, but at least with this you can be sure that your objects
            > are deleted when the Cache object is destroyed. You can even change the
            > implementation of Cache to allow for other methods of organizing the
            > SomeObjects if you find that one huge chunk of memory doesn't work so
            > well. Better still, you can change it to create the objects one at a
            > time in the usual way so that you have something nice and simple to use
            > during testing and debugging, and then possibly stick with if you find
            > that performance is good enough.
            >
            > -Kevin
            > --
            > My email address is valid, but changes periodically.
            > To contact me please use the address from a recent posting.
            >[/color]


            Comment

            • Alf P. Steinbach

              #7
              Re: Dynamically allocated array question

              On Tue, 19 Aug 2003 12:18:10 GMT, "Jeff Williams" <no_spam_remove _up_to_here_jwi lliams@mfchelp. com> wrote:
              [color=blue]
              >Yes my example code was in error, let me post the correct version and clean
              >up my question a little:
              >
              >new example code:
              >
              >struct base_class { };
              >struct derive_class : base_class { };
              >
              >void foo(std::vector <base_class*> & vec)
              >{
              > base_class* pBases = new derive_class[100];
              > for(int i = 0; i < 100; ++i)
              > vec.push_back(& pBases[i]);
              > }
              >
              >void bar(std::vector <base_class*> & vec)
              >{
              > for(int i = 0; i < vec.size(); ++i)
              > delete vec[i];
              > vec.clear();
              >}
              >
              >// I dont give a crap that the main func has bad prototype so dont even
              >bother
              >int main()[/color]

              The prototype is OK.

              Your attitude is not.

              That includes both the language and neglecting to study earlier answers.

              Comment

              Working...