Should I prefer "default" calling convention over __fastcall when I don't really care of the calling convention?
We have a huge C++ codebase with lots of COM objects. Each function exposed to COM must have __stdcall
calling convention (usually STDMETHODCALLTYPE
macro) and so we have lots of functions marked STDMETHODCALLTYPE
.
Now I see a function that is not directly called through COM, but rather called only from within our C++ code and this function also has STDMETHODCALLTYPE
macro in its signature. I'm completely sure that macro is useless there - no calls through COM to that function ever happen.
Should I开发者_运维知识库 drop the __stdcall
so that it becomes a "default" calling convention function? How do I make such decisions?
My approach is to use the default compiler calling convention for internal code and to use a well-defined explicitly stated calling convention for any methods which are exported across a module boundary.
The default calling convention for most compilers makes good use of registers for performance reasons so there are advantages to using it where appropriate. It also makes your code easier on the eye since you don't need to specify the convention to get the default.
For exported functions you clearly need to specify the convention. If you are making a library that you anticipate will be called from languages other than C or C++ it would be conventional to use stdcall. If you only expect C or C++ clients then cdecl is probably the most common convention.
When Windows switched from __cdecl to __stdcall as the default calling convention, the size of the product dropped by about 10%. That savings was entirely related to removing the stack adjustments after calling the stdcall methods (__cdecl is a "caller adjusts the stack to remove parameters" calling convention, __stdcall is a "callee adjusts the stack to remove parameters" calling convention, since there are more callers than callees, switching reduces the size of your binaries).
The downside of using __stdcall is that you don't have variable #s of argments (since the callee adjusts the stack, they can't know how many parameters the caller specified).
Bottom line: switching to __stdcall from the "default" calling convention can result in a reduction in size of your binary. That may or may not be important to you.
However as mkaes mentioned above, if your code is EVER accessed in another compiland (for instance if you deliver a .lib file to someone else), it's absolutely critical that you declare the calling convention used.
The only reason why the COM stuff explicitly sets the calling convention is because it is used across DLL boundaries.
So my advise would be to drop the explicit setting of the calling convention and set it by the compiler settings.
In general:
If the functions are exported as a DLL set a macro that defines the calling convention in the Headers. This prevents users from the DLL to use a wrong calling convention when linking to your DLL. Explicit overrides the compiler setting.
Do not use any calling convection on local functions. Convention can be set by a compiler switch. If you decide to set one explicitly, do it on all Functions. Then you still have a central place to change the calling convention.
Of course if it makes sense or you need some special calling convention e.g fastcall for optimization then you need to set explicitly too.
Do you have whole program optimization and link-time code generation enabled? If so, and you don't export the function from your DLL or pass around pointers to it, then the compiler may generate custom calling conventions for that function or inline it (even if it's not defined in a header file).
You could look through your maps to see if it is referenced, by searching the ODL files associated with the solution. If its not there, it doesn't have an interface, and you can change the calling convention. There is the risk that someone else assumes all functions are set up with this calling convention, and they could add an interface at a later date.
精彩评论