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

As I know, the calling convention depends on the compiler and architecture. But are there any obvious differences between the calling conventions of C and C ++?

+6
source share
5 answers

But are there any obvious differences between the calling conventions of C and C ++?

In general, no. C ++ was specifically designed to be as compatible as possible with C, and in particular, it uses the binary interface of a C application on all systems.

But C ABI does not support the many functions that C ++ needs (in particular, overloading, namespaces and function templates), so the C ++ compiler makes some changes to the function names. This is called name mangling.

So, in order for function calls between C and C ++ code to work, such functions must be declared extern "C" , which disables name management and ensures that calling conventions are expected using C (but I expect this the last aspect comes automatically, even if the standard does not provide for this).

C ++ also has additional calling conventions for member functions (sometimes called thiscall ) that do not exist in C. But free functions use the same calling conventions as C, depending on what is on the system.

+9
source

There is nothing in any standard that requires calling conventions in C and C ++ to be the same in this compiler, except that the declared C ++ extern "C" function must be called with the same call as the C function .

Therefore, for pointer-to-function and pointer-to-function-with-C-relationship with the same parameters and return type, there are different types. When a function is called, the compiler can learn from the type to which the call calls the call, if they are different.

In practice, I donโ€™t think I have ever consciously dealt with an example that uses an incompatible calling convention between free functions with and without C. Typically, a C ++ implementation accepts its calling convention from the ABI system, which it plans to run in order to create related objects (executable files and libraries) that other users of the system can understand from an ABI point of view.

This is not required - the standard does not care if there is an ABI system, and the system usually does not care about how calls are made in a stand-alone executable file [*]. It is simply wise to do this if there is no extraordinary reason. The ABI system in this system may or may not mention C ++ - if not then the C ++ implementation itself does not apply to functions that are not related to C-connection, but, as I said, it is usually reasonable to create functions that could C -link uses the same calling convention as if they had a C-link.

I say "incompatible" and not "different" because of course there are some things that are not mentioned in the C calling convention, but should be specified in the C ++ calling convention. For example, how to pass a member pointer function. It is possible that this is not related to the ABI system, and therefore remains for the implementation of C ++. The reason for this is to leave the implementation of the member-pointer function to the implementation of C ++, and not because the ABI system does what the manufacturer considers the work of the C ++ compiler.

With defiant convention aside, note that a name change inevitably differs between a free function with or without C-link. The reason is that changing the C ++ language name should include parameter types (due to function overload), while a type C name failure should not (due to extern function declarations with undefined parameters).

[*] Although I have seen examples where using the "wrong" calling convention breaks things. ISTR is a Windows mobile device, where if you formatted the stack differently than expected from the OS, then certain hardware exceptions will throw the device out because the OS tried to restore the stack of the calling thread and couldnโ€™t. Therefore, at least on this version of the OS, probably around 2005, if you want the OS diagnostics to work, you had to use internal Windows calls. Or in any case, the portion of the calling convention related to the stack frame format. Of course, this was a complete error, but I donโ€™t know if we could fix it properly by setting our own handlers for hardware exceptions, instead of going around them without causing exceptions in the first place. This meant that the user mode process could trivially remove the OS with a stack overflow, although it was more difficult to debug our code than on other Windows. Therefore, we blamed the OS a little.

+5
source

As I know, the calling convention depends on the compiler and architecture.

Yes.

But are there any obvious differences between the calling conventions of C and C ++?

The best question is: "Are there any similarities?"

Yes:

Declaring functions extern "C" in the C ++ application has the same calling convention, which is used C function in this architecture.

Any other assumptions you make about calling agreements are speculative and may turn out to be the same, but you need to worry about this based on individual cases.

+4
source

The whole concept of various conditional conventions between languages โ€‹โ€‹is beyond the scope of any language (and its specifications). And as it should be, such things do not concern the specification of any language that is worth its name. In principle, you are right, it is in the field of a specific implementation of the specification - the compiler architecture. Of course, some of the concepts discussed in the specification / standard of a given language, such as the specification of bindings, can influence the calling convention, but this is not a planned consequence.

The responsibility of ABI is to standardize / formalize concepts that, again, people are not required to respect (and probably because the colorful palette of implementations varies greatly)

Indeed, the specification should not pay attention to how parameters are passed, whether on the stack or in registers, a combination of them, ordering of the allocation, etc. That the work of the guys working on the implementation and the people who develop the actual equipment, more importantly, sets of instructions.

Therefore: Neither C nor C ++, as standardized, speaks about how the material is implemented. Therefore, there should be no differences inherent in languages. Just the way they are applied. And this is the field of compiler architecture.

+2
source

No standard C or C ++ defines ABI. This is a deliberate design decision that allows compiler authors to create the most efficient implementation possible.

Over time, the C calling convention, called cdecl , has become the de facto standard for x86 architectures. Similar actual standards for C code running on AMD64 machines, but they differ between UNIX and Windows operating systems.

On Unix machines, there is some movement towards a common C ++ ABI, based on Itanium C ++ ABI, published by Intel. However, due to the added complexity of C ++, different versions of the same compiler and even different compiler keys often result in machine code corresponding to incompatible ABIs.

Using extern "C" { ... } can often be used to force the compiler to implement a function using the de facto C ABI, but even this is not required by the C ++ standard.

If you are interested in a detailed description of the current C ++ ABIs, you should look at Agner Fog "Calling Agreements for Different C ++ Compilers and Operating Systems" .

+1
source

Source: https://habr.com/ru/post/919304/


All Articles