This wikipedia page shows an example assembly code of a caller-clean up convention, where the caller cleans the arguments from the stack.
Note: I've removed the provided comments and added my own
int callee(int, int, int);
int caller(void)
{
return callee(1, 2, 3) + 5;
}
caller:
push ebp
mov ebp, esp
push 3
push 2
push 1
call callee
; at this point we returned from callee() and our result is saved in eax
add esp, 12 ; now we clear the stack by adding 12 (space occupied by 3 ints) to esp
add eax, 5
mov esp, ebp ; and here we move the value of ebp to esp, so that "esp = ebp"
; meaning that we could've substracted a million bytes from esp
; instead of just 12 and it wouldn't have made a difference, as we
; are literally assigning a new value to esp here
pop ebp
ret
A similar question was already asked (Why must we clean up the stack) and all the answers say pretty much the same thing: the stack isn't infinite so we must clean it up, but in this case it's not like we are wasting stack memory, the memory occupied by those 3 pushes gets "freed" when we reset the stack frame, making it avaible for later use.