50

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

Mark
  • 8,408
  • 15
  • 57
  • 81
  • If you want to control where a std::string or std::vector allocates its memory, check this question: http://stackoverflow.com/questions/354442/looking-for-c-stl-like-vector-class-but-using-stack-storage – Zan Lynx Jun 13 '11 at 19:14
  • 1
    @Neil: to quickly allocate/free temporary working space? – André Caron Jun 13 '11 at 19:15
  • @Neil Butterworth Example: you need to allocate some variable amount of space for a temporary buffer while you sort vertices by depth. The vertices come in from runtime data, so you don't know in advance how many you'll have. Also, you have a budget of 2 microseconds for the entire function, and on your platform malloc() costs 1 microsecond. – Crashworks Jun 13 '11 at 19:16
  • @Andre So just create local objects as normal - no need for any special facilities. –  Jun 13 '11 at 19:16
  • @Zan: I don't think you can implement an allocator that uses `alloca`. The allocated memory can only be used inside the function that allocates it, so the buffer can't be returned from the allocator! – André Caron Jun 13 '11 at 19:17
  • 2
    @Neil: and if the function needs a small, yet variable, number of temporary objects? You could use a `vector`, but if that function is invoked in a tight loop, it'd be cool if the memory can be quickly allocated and freed without worrying about fragmentation. – André Caron Jun 13 '11 at 19:18
  • @André: The accepted answer to that question does not involve alloca. – Zan Lynx Jun 13 '11 at 19:19
  • @Zan: what OP asked for necessarily involves `alloca`. – André Caron Jun 13 '11 at 19:21
  • 1
    @Andre - Then allocate a small, yet fixed, number of objects on the stack. If we don't know the upper bound, alloca will blow anyway. – Bo Persson Jun 13 '11 at 19:22
  • @André: There are a *lot* of questions on StackOverflow where the question asked is not what the questioner actually needed. – Zan Lynx Jun 13 '11 at 19:23
  • @Bo: sure, but that introduces an extra magic number in the code, and the limit varies based on the machine, compiler flags, etc. (anything that can influence the stack size). If I grow the stack size, I would now need to change 2 sets of settings: the actual stack size *and* the hardcoded limit for my function. – André Caron Jun 13 '11 at 19:24
  • `std::queue` and recursion perhaps as that object is designed for fast continuous allocation. Note in C++ `new` and `delete` are used for heap allocation perhaps this should be re-tagged as C. – AJG85 Jun 13 '11 at 19:40
  • @Neil: `alloca` is used extensively in Microsoft Windows, for temporary string buffers for translating between UTF-16 and Windows ANSI. – Cheers and hth. - Alf Jun 13 '11 at 19:45
  • 1
    @Alf I've been programming for Windows since 2.0 and have never used it, or seen it used., –  Jun 13 '11 at 19:50
  • @Neil: I guess all those calls are hidden in the ANSI versions of the Win32API, since the kernel only processes Unicode versions. – André Caron Jun 13 '11 at 20:23
  • @Neil: as André says. In addition, for your own use, as I recall MFC and ATL define a bunch of macros that package the `alloca`calls. I can look it up if you want, but since I know you're pretty good I don't waste time on that for now. Cheers, – Cheers and hth. - Alf Jun 13 '11 at 23:17
  • See https://stackoverflow.com/questions/354442/looking-for-c-stl-like-vector-class-but-using-stack-storage – Sebastian Jan 26 '22 at 03:02

7 Answers7

60

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!

Community
  • 1
  • 1
Crashworks
  • 40,496
  • 12
  • 101
  • 170
  • 17
    @Neil Butterworth One of many reasons we don't actually use Standard C++ in embedded development. =P – Crashworks Jun 13 '11 at 19:13
  • 1
    what if I use it inside a recursive function? Are there any side effects? Also I don't understand that last part very well, "...blow up if you use it inside a loop". But a loop is still within a function right? – Mark Jun 13 '11 at 19:31
  • @Mark: If you execute alloca in a loop, it'll allocate more memory each iteration, but won't free the memory until you return from the function (whereas a container like `std::vector` local to the loop will be freed at the end of the loop's scope). – Jerry Coffin Jun 13 '11 at 19:38
  • @Mark, you can use it in recursive loop. in normal loop it won't deallocate until the function returns so it can produce a stack overflow, but in recursive loop it will be cleared in each iteration. – Daniel Jun 13 '11 at 19:42
  • @Dani what if the function is a void? – Mark Jun 13 '11 at 20:00
  • 5
    @Mark : Well, stop and think it through. What is alloca() doing, and how does the return type of a function affect it? – Crashworks Jun 13 '11 at 20:46
  • I don't think it makes a difference. – Mark Jun 13 '11 at 21:58
  • 3
    @Crashworks The link is broken and I want to read about your bug! – lmat - Reinstate Monica Nov 15 '18 at 20:32
9

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.

Steve Townsend
  • 53,498
  • 9
  • 91
  • 140
  • 2
    The problem here is that many C++ objects allocate memory for themselves. – Zan Lynx Jun 13 '11 at 19:13
  • @Zan Lynx - sure enough. In what scenario would you allocate such an object graph on the stack though? – Steve Townsend Jun 13 '11 at 19:15
  • 8
    You may call a function that fills in a vector. You might need a string. You might need these things to be very fast and thread safe. If you don't need these things to live beyond the function, then stack storage is exactly the right place. – Zan Lynx Jun 13 '11 at 19:21
  • @Zan - for specialized applications, I can see this. I think if OP had clarified why there is a perceived need for this, I'd be easier to convince. In most cases, my view is it's not needed. – Steve Townsend Jun 13 '11 at 19:24
  • @Steve - I work primarily in embedded environements and frequently my use of heap allocated memory is significantly constrained. – Greg Sep 20 '11 at 19:42
  • @Greg - noted. If OP has such constraints then things may be more complicated for them. – Steve Townsend Sep 21 '11 at 12:00
3

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

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
Dan
  • 1,927
  • 2
  • 24
  • 35
3

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.

DuckMaestro
  • 15,232
  • 11
  • 67
  • 85
  • 1
    This should be the second best answer to that specific question if not the accepted answer. It's clean and simple, unlike the _alloca answer. – MarkoPaulo Oct 27 '17 at 21:30
  • 6
    @MarkusL.Clean simple and *wrong* because the question asks specifically about dynamic (not static) stack allocation. – jeremyong Feb 26 '19 at 20:33
3

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;
}
kapa
  • 77,694
  • 21
  • 158
  • 175
Sammy
  • 31
  • 1
  • 2
    Welcome to SO! Consider quoting the most important bits in your answer, because links might rot. – Mateng Nov 08 '12 at 23:43
  • Hi, welcome to SO! Normaly a answer only pointing to another answer is not considered an answer. see http://meta.stackexchange.com/a/118694 for larification ;-) – Don Question Nov 08 '12 at 23:43
  • Though alloca is one way of doing it, there are fair few drawbacks that makes it a bad practice. Please refer the discussion here; http://stackoverflow.com/a/1018865/83005 – ϹοδεMεδιϲ Nov 08 '12 at 23:43
0

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:

JDiMatteo
  • 12,022
  • 5
  • 54
  • 65
0

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.

T.E.D.
  • 44,016
  • 10
  • 73
  • 134
  • 2
    What question did you answer? – Daniel Jun 13 '11 at 19:13
  • Say what? C++ *does* allow const values for array bounds (if by that you mean array sizes). –  Jun 13 '11 at 19:14
  • Neil Butterworth - lol, Does it? I learned on VC6, so occasionally I hit a "fact" that isn't really true. So you can eg: read an "array size" from a file into a `size_t const` and then use it as an array index size? – T.E.D. Jun 13 '11 at 19:17
  • @T.E.D.: no, you can't. If think Neil understood `static const` where you meant local `const` as in `void f(const int n) { ... }`. – André Caron Jun 13 '11 at 19:20
  • @André Caron - Exactly. I wouldn't call it "obvious" either. Ada allows you to do this exact thing with no qualm whatsoever. Perhaps there is some reason why allowing the same would be injurious in C++, but from my perspective it appears an arbitrary limitation of the language. Until changed, the only standard way around it I know is to make the problem modular and use recursion. – T.E.D. Jun 13 '11 at 19:28
  • ...updated the text to (hopefully) make it clearer to Neil and others. – T.E.D. Jun 13 '11 at 19:34
  • @T.E.D. It isn't going to change - the Standards Committee & the C++ community are vehemently opposed to it, as I have to say are a lot of C users. –  Jun 13 '11 at 19:34
  • @Neil Butterworth - Shame that, but I'm sure they have their reasons. – T.E.D. Jun 13 '11 at 19:36
  • @T.E.D - It is impossible to standardize alloca without requiring all implementations to actually have a stack. If it isn't guaranteed to be stack based it just useless, and we can all use std::vector instead. – Bo Persson Jun 13 '11 at 19:53
  • @Bo I'm not sure about that. C99 has managed to standardise variable array allocation on the stack. The problem is not that you can't standardise it, but that it is a bad idea. –  Jun 13 '11 at 19:56
  • @Neil - I cannot even find the word "stack" in the C99 standard, so how do we know that? – Bo Persson Jun 13 '11 at 20:56
  • @Bo Ok, I meant support for automatic allocation of `int a[n];` where `n` is variable at run-time. And as I enjoy standardese and pedantry as much as the next person, I suspect you knew what I meant :-) –  Jun 13 '11 at 20:59
  • @Neil - I probably know what you mean, but my point is that VLAs are less useful in C++ if they behave like a std::vector anyway. To be an advantage, we need to know that they have a performance advantage. – Bo Persson Jun 13 '11 at 21:16
  • Lol. This has to be just about the most controversial answer with no votes either way ever. There should be a badge of some kind for that. :-) – T.E.D. Jun 14 '11 at 13:04
  • @BoPersson of course there is a performance advantage. Alloca will be many times faster than the malloc that is behind the std::vector. – Jesse Pepper Sep 25 '19 at 04:10