Function call with more parameters than expected
This really depends on the calling convention and architecture. For example, with cdecl
on x86, where arguments are pushed right to left and the caller restores the stack, the presence of an additional parameter is transparent to the function bar
:
push 11
push 10
call _bar
add esp, 8
bar
will only "see" the 10
, and will function as expected with that parameter, returning 100
. The stack is restored afterwards so there is no misalignment in main
either; if you had just passed the 10
it would have added 4 to esp
instead.
This is also true of the x64 calling conventions for both MSVC on Windows and the System V ABI, where the first few1 integral arguments are passed in registers; the second argument will be populated in its designated register by the call in main
, but not even looked at by bar
.
If, however, you tried to use an alternate calling convention where the callee is responsible for cleaning up the stack, you would run into trouble either at the build stage or (worse) at runtime. stdcall
, for example, decorates the function name with the number of bytes used by the argument list, so I'm not even able to link the final executable by changing bar
to use stdcall
instead:
error LNK2019: unresolved external symbol _bar@8 referenced in function _main
This is because bar
now has the signature _bar@4
in its object file, as it should.
This gets interesting if you use the obsolete calling convention pascal
, where parameters are pushed left-to-right:
push 10
push 11
call _bar
Now bar
returns 121, not 100, like you expected. That is, if the function successfully returns, which it won't, since the callee was supposed to clean up the stack but failed due to the extra parameter, trashing the return address.
1: 4 for MSVC on Windows; 6 on System V ABI
Normally you'd have this file structure:
foo.c
#include "foo.h"
int bar(int param1)
{
return param1*param1;
}
foo.h
int bar(int param1);
main.c
#include <stdio.h>
#include "foo.h"
int main (void)
{
int param = 2, unused = 0;
printf("%d\n", bar(param, unused));
}
Now you'll get a compilation error as soon as you use bar
with non matching parameters.