Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the differences between C, and C++ calling conventions?

As I know, the calling convention is compiler and architecture dependent. But are there any clear differences between C and C++ calling conventions?

like image 405
Kadiam Avatar asked Jun 29 '12 06:06

Kadiam


People also ask

What are the C calling conventions?

There are three major calling conventions that are used with the C language on 32-bit x86 processors: STDCALL, CDECL, and FASTCALL. In addition, there is another calling convention typically used with C++: THISCALL. There are other calling conventions as well, including PASCAL and FORTRAN conventions, among others.

What are the calling conventions for C and C++ at the assembly level?

There are different calling conventions available in C/C++: stdcall , extern , pascal , etc.

What is a calling convention Winapi?

A calling convention is a scheme for how functions receive parameters from their caller and how they return a result. The calling conventions can differ in where parameters and return values are placed (in registers; on the call stack; a mix of both), the order they are placed.

What is the calling convention used for a compiler in C++?

thiscall. This calling convention is used for calling C++ non-static member functions. There are two primary versions of thiscall used depending on the compiler and whether or not the function uses a variable number of arguments.


1 Answers

There is nothing in either standard that requires the C and C++ calling conventions to be the same on a given compiler, other than that a C++ function declared extern "C" necessarily must be called with the same calling convention as a C function.

That's why a pointer-to-function and a pointer-to-function-with-C-linkage with the same parameters and return type, have different types. When the function is called, the compiler can know from the type which calling convention to call it with, if they are different.

In practice, I don't think I've ever knowingly dealt with an example that uses an incompatible calling convention between free functions with and without C linkage. Usually a C++ implementation adopts its calling convention from the ABI of the system that it's planning to run on, so as to produce linkable objects (executables and libraries) that other users of the system can understand in terms of the ABI.

This isn't required -- the standard doesn't care whether or not there is a system ABI, and the system doesn't usually care how calls are made within a self-contained executable[*]. It's just sensible to do it unless there's some extraordinary reason not to. The system ABI on a given system may or may not mention C++ -- if not then the C++ implementation is on its own as far as non-C-linkage functions are concerned, but as I say it is usually sensible to make functions that could have C linkage use the same calling convention as if they do have C linkage.

I say "incompatible" rather than "different", because of course there are some things that aren't mentioned in the C calling convention but need to be specified in the C++ calling convention. How to pass a pointer-to-member-function, for example. It may well be that this is not pinned down by the system ABI, and so is left to the C++ implementation. The reason for this is to leave the implementation of pointer-to-member-function up to the C++ implementation, rather than the system ABI doing something that the manufacturer considers to be the job of a C++ compiler writer.

With the calling convention out of the way, note that name mangling inevitably is different between a free function with or without C linkage. The reason is that C++ name mangling must include the types of the parameters (because of function overloading), whereas C name mangling must not (because of extern function declarations with unspecified parameters).

[*] Although I've seen examples where using the "wrong" calling convention does break things. ISTR a Windows mobile device where if you formatted the stack differently from what the OS expected, then certain hardware exceptions would take out the device because the OS tried to retrace the stack of the offending thread, and couldn't. So at least on that OS version, probably around 2005, if you wanted the OS's diagnostics to work then you had to use the Windows calling conventions internally. Or anyway the part of the calling convention relating to stack frame format. This was entirely our screwup, of course, but I don't know whether we could have fixed it properly by installing our own handlers for the hardware exceptions, rather than working around them by not causing the exceptions in the first place. It did mean that a user-mode process could trivially take the OS down with a stack overrun, though, and also that it was harder to debug our code than on other Windowses. So we slightly blamed the OS.

like image 159
Steve Jessop Avatar answered Oct 13 '22 00:10

Steve Jessop