Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Horrid Memory Management Issue

Horrid Memory Management Issue

Scheduled Pinned Locked Moved C / C++ / MFC
helpgraphicsdockerdata-structuresperformance
9 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    Lost User
    wrote on last edited by
    #1

    Hi all, back with a slightly different issue. OK, here's what I'm trying to do: I'm writing a template container class for a dynamic array (similar to the vector class). The class will be used as a basis for my own custom string allocation and more complex class structures. With this in mind, operator new in its standard form has not been implemented because it cannot be used to expand memory, I would, in effect, have to new another block of memory and copy the contents over before deleting the old block, this is slow and prone to mistakes. Therefore malloc has been implemented, with realloc, to handle the actual memory allocations. However, the problem with malloc is that it never calls the constructor for the object you want to store, it just allocates raw bytes. BUT, does this mean I could use placement new to initialise a block of memory with type T as follows: T* p = malloc(sizeof(T)); if(p) { new (p) T; } I would like to be able to call the constructor for each object in the malloc'ated area but similarly I can't use new cos I want it to be fast AND dynamic. Any good links, ideas, suggestions on how I'm going about this would be very much appreciated. This class will be a foundation for many things and I need it to be neat, at the moment it works, but its buggy cos things aren't getting constructed properly. Thanks guys.

    P A 3 Replies Last reply
    0
    • L Lost User

      Hi all, back with a slightly different issue. OK, here's what I'm trying to do: I'm writing a template container class for a dynamic array (similar to the vector class). The class will be used as a basis for my own custom string allocation and more complex class structures. With this in mind, operator new in its standard form has not been implemented because it cannot be used to expand memory, I would, in effect, have to new another block of memory and copy the contents over before deleting the old block, this is slow and prone to mistakes. Therefore malloc has been implemented, with realloc, to handle the actual memory allocations. However, the problem with malloc is that it never calls the constructor for the object you want to store, it just allocates raw bytes. BUT, does this mean I could use placement new to initialise a block of memory with type T as follows: T* p = malloc(sizeof(T)); if(p) { new (p) T; } I would like to be able to call the constructor for each object in the malloc'ated area but similarly I can't use new cos I want it to be fast AND dynamic. Any good links, ideas, suggestions on how I'm going about this would be very much appreciated. This class will be a foundation for many things and I need it to be neat, at the moment it works, but its buggy cos things aren't getting constructed properly. Thanks guys.

      P Offline
      P Offline
      Phil Speller
      wrote on last edited by
      #2

      Well, first off, I've gotta say thanks - I learnt a new thing today - I was never aware of the placement syntax :/ Mixing C-style and C++ style memory allocations is not a good idea since they use separate memory managers. You could replace your malloc(sizeof(T)) with new char[sizeof(T)]. Realloc would still present you with the copying problem - infact, if realloc can't extend the memory area it will create a completely new area and perform a copy operation. It does look like the placement syntax enables you to give an explicit address for the object you wish to dynamically create - it also looks like that will remove the overhead of the memory manager actually finding a suitable sized piece of free memory. So, I am thinking you are on the right track here. [EDIT] One thing I forgot to mention was that when you do use placement new, Stroustrup states that you need to explicitly call destructors for objects when you want to delete them - this makes sense since the memory manager is being bypassed. [/EDIT] However, you may want to consider creating space for several objects each time you need to reserve space i.e. new char[N*sizeof(T)]. Now create you own memory management scheme that uses that pool of memory with placement new. When that area is exhausted, create another pool. This has the effect of reducing the number of times the standard new operator needs to be called - thus reducing overhead. Ok, you have to manage each pool but working with fixed sized objects within each pool should be fairly efficient to to. There is a book called "Efficient C++" which looks at these issues in some detail. Hope this helps Phil

      L 1 Reply Last reply
      0
      • L Lost User

        Hi all, back with a slightly different issue. OK, here's what I'm trying to do: I'm writing a template container class for a dynamic array (similar to the vector class). The class will be used as a basis for my own custom string allocation and more complex class structures. With this in mind, operator new in its standard form has not been implemented because it cannot be used to expand memory, I would, in effect, have to new another block of memory and copy the contents over before deleting the old block, this is slow and prone to mistakes. Therefore malloc has been implemented, with realloc, to handle the actual memory allocations. However, the problem with malloc is that it never calls the constructor for the object you want to store, it just allocates raw bytes. BUT, does this mean I could use placement new to initialise a block of memory with type T as follows: T* p = malloc(sizeof(T)); if(p) { new (p) T; } I would like to be able to call the constructor for each object in the malloc'ated area but similarly I can't use new cos I want it to be fast AND dynamic. Any good links, ideas, suggestions on how I'm going about this would be very much appreciated. This class will be a foundation for many things and I need it to be neat, at the moment it works, but its buggy cos things aren't getting constructed properly. Thanks guys.

        P Offline
        P Offline
        Phil Speller
        wrote on last edited by
        #3

        Also, take a look here[^] for some more info. The bit about alignment is worth noting! Phil

        L 1 Reply Last reply
        0
        • P Phil Speller

          Well, first off, I've gotta say thanks - I learnt a new thing today - I was never aware of the placement syntax :/ Mixing C-style and C++ style memory allocations is not a good idea since they use separate memory managers. You could replace your malloc(sizeof(T)) with new char[sizeof(T)]. Realloc would still present you with the copying problem - infact, if realloc can't extend the memory area it will create a completely new area and perform a copy operation. It does look like the placement syntax enables you to give an explicit address for the object you wish to dynamically create - it also looks like that will remove the overhead of the memory manager actually finding a suitable sized piece of free memory. So, I am thinking you are on the right track here. [EDIT] One thing I forgot to mention was that when you do use placement new, Stroustrup states that you need to explicitly call destructors for objects when you want to delete them - this makes sense since the memory manager is being bypassed. [/EDIT] However, you may want to consider creating space for several objects each time you need to reserve space i.e. new char[N*sizeof(T)]. Now create you own memory management scheme that uses that pool of memory with placement new. When that area is exhausted, create another pool. This has the effect of reducing the number of times the standard new operator needs to be called - thus reducing overhead. Ok, you have to manage each pool but working with fixed sized objects within each pool should be fairly efficient to to. There is a book called "Efficient C++" which looks at these issues in some detail. Hope this helps Phil

          L Offline
          L Offline
          Lost User
          wrote on last edited by
          #4

          Yes, I had thought about allocating a couple of extra places and then when they are filled grabbing a new block and copying the contents in, which is essentially what realloc utilises. This is definitely one option, and is probably the way that the vector class works (in fact you can define its growth factor). However, I was hoping to come up with a nice tight memory usage, that makes things easy to use. The idea of placement new seems like what I want, 'use this memory address to initialise with this item'. I don't think it actually allocates any memory see, just initialises it with the item you supply. As you stated, I'd then have to whip through the array and call the destructor for each object manually, but this can be arranged :). If realloc needed a new memory block, the contents of my already initialise data would be copied in - no destructor is called, which is great because it were, when the array class destructor was called it would delete the same objects again :). I think I may be on the right lines, just waiting for someone to prove otherwise :). Thanks for your comments though Phil, they were very encouraging, which is something I need at the minute cos I've been on this a little while :). Many Thanks, Alan.

          P 1 Reply Last reply
          0
          • P Phil Speller

            Also, take a look here[^] for some more info. The bit about alignment is worth noting! Phil

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #5

            Thanks again Phil, I'm pretty sure alignment won't be a problem because malloc handles the correct alignment for buffers depending on their size (it doesn't matter exactly what object they are, only the size of the object will determine whether malloc has to pad the memory with x bytes to align it :)). Cheers for that article mind, very helpful explanation of placement new, which is new :) to me myself. Thanks again for your help Phil, much appreciated, Alan.

            1 Reply Last reply
            0
            • L Lost User

              Yes, I had thought about allocating a couple of extra places and then when they are filled grabbing a new block and copying the contents in, which is essentially what realloc utilises. This is definitely one option, and is probably the way that the vector class works (in fact you can define its growth factor). However, I was hoping to come up with a nice tight memory usage, that makes things easy to use. The idea of placement new seems like what I want, 'use this memory address to initialise with this item'. I don't think it actually allocates any memory see, just initialises it with the item you supply. As you stated, I'd then have to whip through the array and call the destructor for each object manually, but this can be arranged :). If realloc needed a new memory block, the contents of my already initialise data would be copied in - no destructor is called, which is great because it were, when the array class destructor was called it would delete the same objects again :). I think I may be on the right lines, just waiting for someone to prove otherwise :). Thanks for your comments though Phil, they were very encouraging, which is something I need at the minute cos I've been on this a little while :). Many Thanks, Alan.

              P Offline
              P Offline
              Phil Speller
              wrote on last edited by
              #6

              Alan, You shouldn't need to perform any copying. The idea of creating a memory block/pool that is several times larger than the object(s) you want to place within it is to reduce the number of times malloc or new are called (not placement new). When you have filled that block, allocate another and start using that one (you will now have two blocks containing object - there should be no need to copy the contents of your original block to the second one). Keep doing this for as long as you need space to store your objects. A scheme such as a two-way linked list that forms a header at the top of each block will enable you to keep track of each one allocated - and provide a mechansim to remove blocks once all the objects it contains are deleted. This should still be fairly efficient. Actually, I'm pretty sure this is how vector is implemented and I think the growth factor effectively determines the block/pool size used. Cheers, Phil

              L 1 Reply Last reply
              0
              • P Phil Speller

                Alan, You shouldn't need to perform any copying. The idea of creating a memory block/pool that is several times larger than the object(s) you want to place within it is to reduce the number of times malloc or new are called (not placement new). When you have filled that block, allocate another and start using that one (you will now have two blocks containing object - there should be no need to copy the contents of your original block to the second one). Keep doing this for as long as you need space to store your objects. A scheme such as a two-way linked list that forms a header at the top of each block will enable you to keep track of each one allocated - and provide a mechansim to remove blocks once all the objects it contains are deleted. This should still be fairly efficient. Actually, I'm pretty sure this is how vector is implemented and I think the growth factor effectively determines the block/pool size used. Cheers, Phil

                L Offline
                L Offline
                Lost User
                wrote on last edited by
                #7

                Yeah I see what your saying, its just because I'm creating a template container class for arrays of objects (I've already done one for linked lists), so I didn't really want to mess with having multiple new'd pointers (I wanted to be able to use pointer addition :)). Your right about the vector implementation, but I'm looking for a way of manipulating one contigous block of memory. I had thought of reserving larger chunks, and your solution of reserving another chunk is smart, but I'd like to see how much I can squeeze out one contigous memory block before I opt for plan B. :) Alan.

                1 Reply Last reply
                0
                • L Lost User

                  Hi all, back with a slightly different issue. OK, here's what I'm trying to do: I'm writing a template container class for a dynamic array (similar to the vector class). The class will be used as a basis for my own custom string allocation and more complex class structures. With this in mind, operator new in its standard form has not been implemented because it cannot be used to expand memory, I would, in effect, have to new another block of memory and copy the contents over before deleting the old block, this is slow and prone to mistakes. Therefore malloc has been implemented, with realloc, to handle the actual memory allocations. However, the problem with malloc is that it never calls the constructor for the object you want to store, it just allocates raw bytes. BUT, does this mean I could use placement new to initialise a block of memory with type T as follows: T* p = malloc(sizeof(T)); if(p) { new (p) T; } I would like to be able to call the constructor for each object in the malloc'ated area but similarly I can't use new cos I want it to be fast AND dynamic. Any good links, ideas, suggestions on how I'm going about this would be very much appreciated. This class will be a foundation for many things and I need it to be neat, at the moment it works, but its buggy cos things aren't getting constructed properly. Thanks guys.

                  A Offline
                  A Offline
                  antlers
                  wrote on last edited by
                  #8

                  I'm not sure realloc will be more efficient than doing another new and copying. That's what realloc does beneath the surface, anyway. You only literally 'expand' an allocated space with realloc on those rare occasions where you have not done any other memory allocations since you malloc'd the memory you are expanding. I'd look into how efficient you can get the STL using custom allocator classes before you go as far as reimplementing a string class.

                  L 1 Reply Last reply
                  0
                  • A antlers

                    I'm not sure realloc will be more efficient than doing another new and copying. That's what realloc does beneath the surface, anyway. You only literally 'expand' an allocated space with realloc on those rare occasions where you have not done any other memory allocations since you malloc'd the memory you are expanding. I'd look into how efficient you can get the STL using custom allocator classes before you go as far as reimplementing a string class.

                    L Offline
                    L Offline
                    Lost User
                    wrote on last edited by
                    #9

                    I think realloc will be faster when it comes to large objects because it will merely allocate a larger block of memory and copy the contents over - no destructors or constructors are called, therefore everything is A1. Also, new does have extra overhead because of the try,throw,catch implementation. However, using new/delete I'd have to reserve another memory block, but how pray do I move the objects into the new array? If I merely copy the bytes across, when I free up the previous allocation the objects destructor is called and so, those objects in the new array are total garbage (and they will get deleted again the next time a reallocation is made. Nasty. Any ideas on how to get around that would be very useful, and I would definitely use that method instead :). Cheers, Alan.

                    1 Reply Last reply
                    0
                    Reply
                    • Reply as topic
                    Log in to reply
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes


                    • Login

                    • Don't have an account? Register

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • World
                    • Users
                    • Groups