The typical build memory statistics is:
Global variables use XXX bytes (X%) of dynamic memory,
leaving YYY bytes for local variables.
Maximum is ZZZ bytes.
What is all this about? First, the maximum number of bytes SRAM depends on the MCU. Arduino Uno is ATmega328 based and has 2K byte SRAM. Arduino Mega2560 has 8K byte. "Dynamic memory" in the print out is SRAM. It is not the heap (malloc/free). To avoid confusion I will use "data memory" below.
The compiler allocates memory for all global variable (objects, struct, etc). It also allocates memory for literal strings (character vectors). These are copied from program memory to data memory at startup. All static variables in functions are also allocated. The sum of all these allocations are the "Global variables".
To execute the sketch data memory is used for the stack. It contains the function parameters, local variables in called functions (that are not allocated to registers), saved registers such as return address to the caller, etc. The size of the frame is known by the compiler and may be found in the assembly listing of a sketch. The maximum stack size required is tricky to calculate as it is the call chain with the largest frame size sum. This is not necessarily the deepest call chain. Also the compiler does to a fair amount of inlining.
The heap (malloc/free) is used by classes such as String. The heap starts directly after the global variables in data memory and grows towards the stack. The heap is blocks of memory allocated and deallocated during the execution of the sketch. This behavior may give heap fragmentation.
Interrupt Service Routines (ISR) need to be able to execute "on top of" any function call. The ISRs are typically called on hardware events such as USART data received. The compiler has to generate code that stores the machine state on stack to execute the ISR. Depending on how many registers the ISR needs more or less of the machine state (registers) need to be stored. The worst case is all 32 registers.
The warning at 30% of SRAM is at approx. 600 bytes left (Arduino Uno, 2K byte). That has to cover the stack and possible heap usage together with ISRs. With a stack heap limit of 32-128 byte, ISR frame of 32-64 byte, that actually leaves worst case approx. 400 bytes for local variables in functions and possible usage of the heap (such as String).