Programmation C++/Conventions d'appel

Un livre de Wikilivres.

Convention d'appel[modifier | modifier le wikicode]

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 connaît assurément le nombre de paramètres qu'il a empilé.

Spécifier la convention d'appel[modifier | modifier le wikicode]

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 : 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[modifier | modifier le wikicode]

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
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[modifier | modifier le wikicode]

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.

Liens[modifier | modifier le wikicode]

Références[modifier | modifier le wikicode]

  1. http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html