Programmation C++/Conventions d'appel


Convention d'appelModifier

Une 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 connait assuremment le nombre de paramètres qu'il a empilé.

Spécifier la convention d'appelModifier

La 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'objet this. Ce mot clé ne peut être utilisé.
  • pascal :
  • vectorcall :


Différences entre les conventions d'appelModifier

Convention 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


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égats.

Nommage des fonctionsModifier

Pour é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.

LiensModifier