A few c++ questions

Hi guys,

I have a few general c++ questions :

I) I know I have to avoid memory allocation in the audio thread.
But regarding heap stack allocation, what memory allocation size can potentially be a problem?
(I’m not talking performance here, but about locking issue and other unpredictable time behaviour)

void audioProcess()
   float a = 0.0f;       // I guess it's ok!
   float b[16384] = {};  // potential issue here?

what about float c[4] or float d[128] ?
Is it always safe, or is there a specific limit ?

II) Talking about the heap stack, what’s its size on modern OSs?

III) If I need a buffer for some audio data (to build a -mono- ring buffer for instance), should I rather use HeapBlock<float>, AudioBuffer<float>, or std::vector<float> ?
is std::vector slower than a standard array?

Thank you all for your insights

float b[16384] = {};

Involves no heap allocation. The array declared this way will always be placed on the stack, the same is true for directly declaring variables like float a = 0.0f, using std::array or using alloca.

So why do we allocate at all? Because stack size is limited, the compiler will build code that uses super big stack arrays but this will crash at runtime with a stack overflow. Heap allocation on the other hand is not that limited, the size of your heap is nearly your machines whole RAM size plus Hard Disk Swap space the OS uses if it runs out of RAM space.

As you mentioned, there are several ways to allocate heap memory, from plain C malloc calls to the usage of containers like std::vector. The memory they allocate is the same, so access speed to the raw memory is equal for all of them. However containers have the ability to re-allocate if you change their size at runtime, which will obviously take some time, which might slow critical parts of the code down. On the other hand this simplifies a lot of not so time critical problems. So it mostly depends on how you use them.

1 Like

It is worth remembering, what a stack is, and why it is safe as opposed to heap space:

A stack is a last in-first out data structure and is present during the whole life time of the process/thread. Since there is no random creation/destruction of memory, it cannot fragment by design, and it cannot swap out. So there is no OS call involved when putting a variable on the stack, it is only moving the stack pointer by the size of the thing you put on the stack.

On the other hand the stack space is static and limited, if it’s full, it’s end of life (the infamous stack overflow).

About your question of heap space, that is the specs of your machine, the installed RAM plus virtual RAM on disk (swap space). There is a huge span possible, only limited by the address size.

I would be curious, how big is the typical stack memory?

1 Like

oops. Sorry, I mean stack, not heap!
Everywhere I wrote ‘heap’ you should read ‘stack’ :grimacing:
So my questions were :

  • is it always safe (as long as I don’t exceed the stack size) to do memory allocation on the stack in the audio thread? Will that never imply any locking or unpredictable time behaviour as with heap allocation?
  • what is the stack size on modern OSs?

still curious about the vector vs array to handle audio data also.

Stack allocation is a constant time operation, basically just an addition (or subtraction) of a pointer, and it doesn’t matter how big the allocation is. And it happens in the context of the running thread, so there are no locks or surprising memory sharing going on. (Each thread has its own stack.)

The default stack size is probably something like 1-2 megabytes. It can be made larger with build time options. (But you probably shouldn’t go crazy with it, using stack memory indiscriminately isn’t necessarily a proper solution for allocation issues.)

1 Like

Technically you don’t allocate memory on the stack, and you don’t de-allocate. The stack memory is always there. You put data on the stack, which is (like I said before and Xenakios repeated) just moving the stack pointer by the size of the thing you put on the stack, be it a float or an array.
It can’t be anything of a dynamic size. When a scope ends, it is simply moving the stack pointer backwards, calling the destructor of each element on the stack.