What Is the Meaning and Usage of _Stdcall

What is the meaning and usage of __stdcall?

All functions in C/C++ have a particular calling convention. The point of a calling convention is to establish how data is passed between the caller and callee and who is responsible for operations such as cleaning out the call stack.

The most popular calling conventions on windows are

  • __stdcall, Pushes parameters on the stack, in reverse order (right to left)
  • __cdecl, Pushes parameters on the stack, in reverse order (right to left)
  • __clrcall, Load parameters onto CLR expression stack in order (left to right).
  • __fastcall, Stored in registers, then pushed on stack
  • __thiscall, Pushed on stack; this pointer stored in ECX

Adding this specifier to the function declaration essentially tells the compiler that you want this particular function to have this particular calling convention.

The calling conventions are documented here

  • https://learn.microsoft.com/en-us/cpp/cpp/calling-conventions

Raymond Chen also did a long series on the history of the various calling conventions (5 parts) starting here.

  • https://devblogs.microsoft.com/oldnewthing/20040102-00/?p=41213

What is __stdcall?

__stdcall is the calling convention used for the function. This tells the compiler the rules that apply for setting up the stack, pushing arguments and getting a return value.

There are a number of other calling conventions, __cdecl, __thiscall, __fastcall and the wonderfully named __declspec(naked). __stdcall is the standard calling convention for Win32 system calls.

Wikipedia covers the details.

It primarily matters when you are calling a function outside of your code (e.g. an OS API) or the OS is calling you (as is the case here with WinMain). If the compiler doesn't know the correct calling convention then you will likely get very strange crashes as the stack will not be managed correctly.

What is advantage/use of __stdcall?

opcua_client::onShutdownMessage looks like callback function. That is, a function that is sent to some API which calls the function at a later time. The callback function must then have the calling convention expected by the API, in this case __stdcall. Since __stdcall is the default calling convention on the Win32 platform, it does not have to be specified when building for Win32.

Plainly and simply, why do we use _stdcall?

The reason for having some calling convention is pretty simple: so that the caller and the callee agree on how things will work. Without it, the caller doesn't know where to put arguments when it's calling a particular function.

As for why Microsoft decided on the specific details of _stdcall, that's largely historical. On MS-DOS, all calls were register based, so all OS calls required assembly language, or strange extensions to most higher-level languages.

When they first did Windows, they used the cdecl calling convention, mostly because that's what the compiler did by default. At least according to rumor, shortly before they got ready to release Windows 1.0, they switched to the Pascal calling convention because it was enough more efficient that (among other things) it allowed Windows to fit on one fewer floppy disc. Regardless of the precise details, the Pascal calling convention did make code a little smaller, because the called function cleaned up the arguments from the stack instead of needing to clean them up everywhere the function was called. For any function that was called from at least 2 different places, that's a win (and if it's tie anywhere else).

Then they started work on OS/2, and invented yet another calling convention (syscall).

Then, of course, came Win32. There wasn't really a lot wrong with syscall from a technical viewpoint, but (I'd guess) everything associated with OS/2 was considered tainted, so syscall had to go. The result was something just enough different to justify a new name. In fairness, that's a little bit of an exaggeration: they did add one truly useful addition: they encoded the number of bytes of arguments into each function name, so if (for example) you supplied an incorrect prototype for a function, the code wouldn't link rather than ending up with a mismatch between caller and callee that could lead to much more serious problems.

For the most part, it really comes back to the original point though: the exact details of the calling convention don't matter all that much, as long as you don't make a complete mess of it. Most of what matters is that the caller and callee agree on the same thing, so if a compiler knows what parameters a function accepts, it knows how to generate code to get those parameters to the function correctly (and, likewise, they both agree on how stack cleanup is handled, etc.)

Why use __stdcall for function pointer

Embedding a calling convention specifier in a function pointer allows you to use that calling convention when calling functions through that pointer. __stdcall is the calling convention used to call Win32 API functions.

The benefit of specifying it in a function pointer is being able to match a different calling convention according to your code's needs (e.g. when loading an external library's function via late binding). Library headers should specify them as a good programming practice.

There's a caveat though: if you embed a wrong calling convention in a function pointer, the compiler might be powerless to help you detect that and you might end up doing bad things at runtime.

Is there STDCALL in Linux?

The simplest solution is to just define __stdcall to nothing conditionally on Linux.

When using PInvoke, why use __stdcall?

There is only one calling convention on x64 and so it does not matter which calling convention you specify. It is always ignored on x64.

On x86 it is important to make sure calling conventions match on both sides of the interface. So if you ever anticipate running your code on x86 it would be prudent to get that right now.

Does every function in a Windows GUI application need to use stdcall?

WinMain is declared with __stdcall and calls all the functions I've defined. Does this mean all the functions I define should use the stdcall calling convention?

No. Calling conventions are handled on a per-function-call basis, right at the call site. The convention dictates how the caller and callee manage the call stack - how parameters are passed, in what order, who cleans up the stack, etc. As long as the caller and callee agree to use the same calling convention on each individual function call, it is perfectly safe for a stdcall function to call a function that uses a different convention, like cdecl, and vice versa. A function's calling convention applies only when:

  • the function is being entered by a new caller.
  • the function is returning back to that caller.
  • the function is accessing its own parameters.

Outside of that, what a function does internally has nothing to with its own calling convention.

For example, lets say that WinMain(), a stdcall function, wants to call a cdecl function.

It does not matter at all that WinMain() is itself a stdcall function. While code execution is inside of WinMain(), it can do whatever it wants. WinMain()'s stdcall convention is applied only upon entry and exit of WinMain() itself. That is the contract WinMain() has with ITS caller.

What matters is that WinMain() must follow the rules of cdecl when setting up the call stack for a cdecl function that it is about to call into, and cleaning up the call stack when that function returns back to WinMain().

The same goes for any function call of any calling convention.

I've tried not using __stdcall and nothing bad happened. I have also seen well-known GUI libraries supporting Windows don't use stdcall. Why is the stack not corrupting?

Because the call stack is being managed correctly at every function call and return, so there is no unbalanced cleanup to corrupt the stack.



Related Topics



Leave a reply



Submit