开发者

C++ How to allocate memory dynamically on stack?

开发者 https://www.devze.com 2023-03-12 08:59 出处:网络
Is there a way to allocate memory on stack instead of 开发者_C百科heap? I can\'t find a good book on this, anyone here got an idea?Use alloca() (sometimes called _alloca() or _malloca() ), but be very

Is there a way to allocate memory on stack instead of 开发者_C百科heap? I can't find a good book on this, anyone here got an idea?


Use alloca() (sometimes called _alloca() or _malloca() ), but be very careful about it — it frees its memory when you leave a function, not when you go out of scope, so you'll quickly blow up if you use it inside a loop.

For example, if you have a function like

int foo( int nDataSize, int iterations ) 
{
   for ( int i = 0; i < iterations ; ++i )
   {
      char *bytes = alloca( nDataSize );
      // the memory above IS NOT FREED when we pass the brace below!
   } 
   return 0;
}  // alloca() memory only gets freed here

Then the alloca() will allocate an additional nDataSize bytes every time through the loop. None of the alloca() bytes get freed until you return from the function. So, if you have an nDataSize of 1024 and an iterations of 8, you'll allocate 8 kilobytes before returning. If you have an nDataSize= 65536 and iterations = 32768, you'll allocate a total 65536×32768=2,147,483,648 bytes, almost certainly blowing your stack and causing a crash.

anecdote: You can easily get into trouble if you write past the end of the buffer, especially if you pass the buffer into another function, and that subfunction has the wrong idea about the buffer's length. I once fixed a rather amusing bug where we were using alloca() to create temporary storage for rendering a TrueType font glyph before sending it over to GPU memory. Our font library didn't account for the diacritic in the Swedish Å character when calculating glyph sizes, so it told us to allocate n bytes to store the glyph before rendering, and then actually rendered n+128 bytes. The extra 128 bytes wrote into the call stack, overwriting the return address and inducing a really painful nondeterministic crash!


Since this is tagged C++, typically you just declare the objects you need in the correct scope. They are allocated on the stack, and guaranteed to be released on scope exit. This is RAII, and a critical advantage of C++ over C. No mallocs or news, and especially no allocas, required.


You can declare a local char[1024] or whatever number of bytes you'd like (up to a point), then take the address of the local for a pointer to this block of memory on the stack. Not exactly dynamic, but you could then wrap up this memory with your own memory manager if desired.


See _malloca.​​​​​​​​​​​​​​​ ​


Article discussing about dynamic memory allocation

We can allocate variable length space dynamically on stack memory by using function _alloca. This function allocates memory from the program stack. It simply takes number of bytes to be allocated and return void* to the allocated space just as malloc call. This allocated memory will be freed automatically on function exit.

So it need not to be freed explicitly. One has to keep in mind about allocation size here, as stack overflow exception may occur. Stack overflow exception handling can be used for such calls. In case of stack overflow exception one can use _resetstkoflw() to restore it back.

So our new code with _alloca would be :

int NewFunctionA()
{
   char* pszLineBuffer = (char*) _alloca(1024*sizeof(char));
    …..
  // Program logic
     ….
  //no need to free szLineBuffer
  return 1;
}


When/if C++ allows the use of (non-static) const values for array bounds, it will be easier.

For now, the best way I know of is via recursion. There are all kinds of clever tricks that can be done, but the easiest I know of is to have your routine declare a fixed-sized array, and fill and operate on what it has. When its done, if it needs more space to finish, it calls itself.


You could use the BDE C++ library, e.g.

const int BUFFER_SIZE = 1024;
char      buffer[BUFFER_SIZE];

bdlma::BufferedSequentialAllocator allocator(buffer, BUFFER_SIZE);
bsl::vector<int>                   dataVector(&allocator);

dataVector.resize(50);

BDE supplies comprehensive allocator options along with collections like bsl::vector that can use polymorphic allocators without changing the type of the container.

You might also consider:

  • https://github.com/facebook/folly/blob/master/folly/docs/small_vector.md
  • http://www.boost.org/doc/libs/1_55_0/doc/html/container/non_standard_containers.html#container.non_standard_containers.static_vector
  • http://llvm.org/docs/doxygen/html/classllvm_1_1SmallVector.html
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号