简体   繁体   中英

C++: allocation in a fixed block of memory in a loop

I have an application which basically goes like this:

Init();
while(true){
    read_data();
    process_data();
    write_processed_data();
}

the data allocated in a passage of the loop is entirely discarded once we have finished write_processed_data. What's more the amount of allocation in each loop passage is bounded by a constant.

I thought I could allocate by using something using a placement new on a moveable pointer inside a fixed size block, and then at the end of the loop passage I just reset the "moveable pointer" to the start of the block, thus avoiding delete altogether. However my attempts have not been very successful, it seems harder to achieve than initially planned. Is this a common allocation strategy? In a program of this kind I could gain in speed and not have to worry about memory leaks.

IF you have a upper bound you do not need the heap in the first place.

That is the best solution.

Thanks to @EdHeal for pointing out the basic idea behind the following approach:

Before your loop, within your block of memory "allocate" large-enough arrays of all the concrete data types you will need to use. Use these as your set of object pools. Unlike the typical implementation of object pools, you never have to grow your pools, because when you create the arrays at the start you you know an upper bound on the number of objects of each type that you might use. (Your problem statement implies that you have this information at least before entering the loop.)

During the loop, each time you need a new object, get its pointer from its pool. You can implement a function that puts the pointer back in the pool to be used as a "new" object again, or if there is a known limit on the total number of "new allocations" that isn't too much greater than the highwater number of objects in use at any one time, you don't even need to bother putting objects back in the pool. (The second option would make the pool management very easy, as all you have to do is keep count of the number of objects that have been taken from each pool, and that tells you which object is the next "new" one.) In either case, at the end of the loop, you reset the pools so that all objects are available to be "new" again.

I'd probably create a class called something like Allocator to manage the pools, with a function for each kind of object it can take from the pool or put back in the pool and a reset() function to call at the end of the loop. There may be more elegant ways to do the job.

Note that if you know the upper bounds of your required numbers of objects precisely enough, well enough in advance, you can create all of the above-mentioned data structures without putting anything on the heap.

One way to avoid lots of unneeded news and deletes is to use an object pool and override a class's new and delete operators. Basically:

// In header file
class Thing{...}

// In .cc file
namespace thingpool {
static std::vector<Thing*>* chunks = 0;
} 

void* Thing::operator new(size_t size){
  // If pool is not initialized
  if (!thingpool::chunks){
    thingpool::chunks = new std::vector<Thing*>;
    thingpool::chunks->reserve(100);  // or some upper bound on expected Things
  }

  void* memptr;
  if(!thingpool::chunks->empty()) {
    memptr = thingpool::chunks->back();
    thingpool::chunks->pop_back();
  } 
  else {
    memptr = ::malloc(size);
  }
  return memptr;
}

// put memory back in pool
void Thing::operator delete(void* ptr)
{
  if (thingpool::chunks)
    thingpool::chunks->push_back(static_cast<key*>(ptr));
}

And clean up the thing pool at some point.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM