What happens, memory-wise, when I call a function from another function? I'm inspecting where the memory is used in an application which runs on Arduino. To my surprise, there are several locations where 100 to 200 bytes are consumed by simply calling a function. Example:
void Dispatcher::processCommand() {
    ...
    displayMemory();
    this-&gt;process(this-&gt;instruction);
}

void Dispatcher::process(const Instruction &amp;instruction) {
    displayMemory();
    if (instruction.length &gt; 0) {
        ...
        return;
    }

    ErrorResponse::componentNotFound(instruction).output(this-&gt;serial);
    TerminationResponse(instruction.commandId, 0xFF).output(this-&gt;serial);
}

The first call to displayMemory() will report that there is 351 bytes left. The second one will tell that only 159 bytes remain (that is, 192 bytes less).
If I alter the body of the process function, the difference between the two memory reports vary. For instance, if I remove the two last lines, the difference drops from 192 bytes to 12 bytes.
I don't understand why this happens. I was thinking that between the moment I'm ready to call a function and a moment when the function starts, the memory should be used exclusively by the additional element in the call stack (the aforementioned 12 bytes maybe?) and the copying of the parameters passed by value (none here). Why is this not the case? What really happens under the hood?
The clue is in those last two lines:
    ErrorResponse::componentNotFound(instruction).output(this-&gt;serial);
    TerminationResponse(instruction.commandId, 0xFF).output(this-&gt;serial);

Let's tear them apart and see what they actually do.
ErrorResponse::componentNotFound(instruction).output(this-&gt;serial);

Call the static function componentNotFound with your instruction, then take the object that is returned, and call the output() method on it passing this-&gt;serial as a parameter.
The hint there is take the object that is returned.
componentNotFound() returns an object. That object has to be stored somewhere. That &quot;somewhere&quot; is on the stack.  And stack space is allocated during the function preamble.  That's the bit of code that runs at the start of the function allocating stack, pushing registers to the stack, etc.
The same happens in the second line:
TerminationResponse(instruction.commandId, 0xFF).output(this-&gt;serial);

Create a new TerminationResponse object and call the output method.
All that goes on the stack.
It's not the calling of the function that is using the memory, it's what the function is doing that is using the memory.