Programmation C++/Conventions d'appel
Convention d'appel
modifierUne convention d'appel à une fonction définit la manière d'appeler une fonction. La manière varie selon le langage de programmation, le compilateur, et parfois l'architecture du processeur cible.
En C++ la convention d'appel définit les points suivants :
- l'ordre d'empilage des paramètres (à partir du premier, ou du dernier),
- passage de certains paramètres dans les registres,
- appel avec une adresse longue ou courte (selon la localisation en mémoire de la fonction),
- désempilage des paramètres effectué par la fonction appelée ou le code appelant,
- méthode de récupération de la valeur retournée.
Pour l'avant dernier point, le désempilage des paramètres est toujours effectué par le code appelant lorsque la fonction a un nombre variable d'arguments, car seul le code appelant connaît assurément le nombre de paramètres qu'il a empilé.
Spécifier la convention d'appel
modifierLa convention d'appel est spécifiée juste avant le nom de la fonction. Parmi les conventions d'appel possibles :
__cdecl
: Convention d'appel par défaut du C et du C++ quand la fonction est définie en dehors de toute classe, ou comporte un nombre variable d'arguments,__stdcall
: Convention d'appel utilisé par l'API Windows,__fastcall
: Passage de certains paramètres dans les registres,thiscall
: Convention d'appel utilisée implicitement par défaut par les fonctions définies dans une classe car il ajoute un paramètre supplémentaire : la référence à l'objetthis
. Ce mot clé ne peut être utilisé.pascal
: Convention d'appel basée sur celle du Turbo Pascal.vectorcall
: (depuis Visual Studio 2013) Convention d'appel pour résoudre les problèmes d'efficacité des applications multimédia (vidéo, audio, jeux vidéo, ...) autorisant le passage de paramètres larges dans les registres.
Les noms des conventions cités ci-dessus sont ceux supportés par Visual C++.
GCC supporte également la plupart de ces conventions d'appel, mais doivent être spécifiées comme attribut avec __attribute__((...))
dans la déclaration de la fonction[1] :
__attribute__((cdecl))
,__attribute__((thiscall))
,__attribute__((stdcall))
,__attribute__((syscall_linkage))
,__attribute__((far))
,__attribute__((near))
,__attribute__((pcs))
,__attribute__((longcall))
,__attribute__((shortcall))
,__attribute__((long_call))
,__attribute__((short_call))
,- ...
Certaines conventions peuvent être spécifiques à une famille de processeurs.
Différences entre les conventions d'appel
modifierConvention | Paramètres dans les registres | Empilage des paramètres | Dépilage des paramètres |
---|---|---|---|
__cdecl
|
aucun | de droite à gauche | par le code appelant |
__stdcall
|
aucun | de droite à gauche | par la fonction appelée |
__fastcall
|
les 2 premiers arguments de taille inférieure à 32 bits | de droite à gauche | par la fonction appelée |
thiscall
|
aucun | de droite à gauche | par la fonction appelée |
pascal
|
aucun | de gauche à droite | par la fonction appelée |
Si la convention d'appel utilisée par le code appelant ne correspond pas à celui de la fonction appelée, la fonction ne comprend pas l'appel effectué et peut causer des dégâts.
Nommage des fonctions
modifierPour éviter des problèmes lors de l'édition de liens avec les librairies externes (extension .dll
sous Windows, .so
sous Unix/Linux), le compilateur nomme les fonctions selon les critères suivants :
- Nom de la fonction,
- Type des arguments,
- Convention d'appel utilisée,
- Type des exceptions lancées,
- Nom de la classe où se situe la fonction.
Chaque compilateur utilise un nommage différent.
Par exemple, pour la fonction void h(int, char)
le nom généré dépend du compilateur :
- GCC 3+, Clang 1+ :
_Z1hic
- GCC 2.9x :
h__Fic
- Microsoft Visual C++ :
?h@@YAXHD@Z
- Borland C++ :
@h$qizc
- SunPro CC :
__1cBh6F_v_
- ...
Il est donc difficile d'utiliser une librairie qui n'a pas été compilée avec le même compilateur que l'application l'utilisant.
Liens
modifier- (anglais) Calling Convention
- (anglais) X86 Calling Convention
- (anglais) Calling Conventions in Microsoft Visual C++
- (anglais) Name mangling