31 votes

Quelles sont les étapes de la compilation d'un programme C++ ?

Les étapes de la compilation d'un programme C++ sont-elles spécifiées par la norme ?

Si oui, quelles sont-elles ?

Sinon, une réponse pour un compilateur largement utilisé (Je préférerais MSVS) serait formidable.

Je parle de prétraitement, de tokenisation, d'analyse syntaxique et autres. Quel est l'ordre dans lequel ils sont exécutés et que font-ils en particulier ?

EDIT : Je sais ce que font la compilation, la liaison et le prétraitement, je suis surtout intéressé par les autres et l'ordre. Les explications à ce sujet sont bien sûr les bienvenues, car je ne suis peut-être pas le seul à vouloir une réponse.

45voto

Keith Thompson Points 85120

Les étapes de la compilation d'un programme C++ sont-elles spécifiées par la norme ?

Oui et non.

La norme C++ définit 9 "phases de traduction". Citation de le projet N3242 (10MB PDF), daté du 2011-02-28 (avant la publication de la norme officielle C++11), section 2.2 :

La préséance parmi les règles syntaxiques de traduction est spécifiée par les phases suivantes [voir note de bas de page] .

  1. Les caractères du fichier source physique sont mis en correspondance, d'une manière définie par l'implémentation, avec le jeu de caractères source de base. (en introduisant des caractères de nouvelle ligne pour les indicateurs de fin de ligne) si nécessaire. [SNIP]
  2. Chaque occurrence d'une barre oblique inversée (\) immédiatement suivie d'un caractère de nouvelle ligne est supprimée, ce qui permet d'épisser les lignes sources physiques pour former des lignes sources logiques. pour former des lignes sources logiques. [SNIP]
  3. Le fichier source est décomposé en jetons de prétraitement (2.5) et en séquences de caractères d'espace blanc (y compris les commentaires). [SNIP]
  4. Les directives de prétraitement sont exécutées, les invocations de macro sont développées et les expressions d'opérateurs unaires _Pragma sont exécutées. [SNIP]
  5. Chaque membre du jeu de caractères source dans un littéral de caractère ou un littéral de chaîne, ainsi que chaque séquence d'échappement et nom de caractère universel. dans un littéral de caractère ou un littéral de chaîne non brute, est converti en le membre correspondant du jeu de caractères d'exécution ; [SNIP]
  6. Les jetons littéraux de chaîne adjacents sont concaténés.
  7. Les caractères d'espace blanc séparant les jetons ne sont plus significatifs. Chaque jeton de prétraitement est converti en un jeton. (2.7). Le site jetons résultants sont analysés syntaxiquement et sémantiquement et traduits comme une unité de traduction. [SNIP]
  8. Les unités de traduction et les unités d'instanciation traduites sont combinées comme suit : [SNIP]
  9. Toutes les références à des entités externes sont résolues. Les composants de la bibliothèque sont liés pour satisfaire les références externes à des entités non définies dans la base de données traduction actuelle. Toutes ces sorties du traducteur sont rassemblées dans une image de programme qui contient les informations nécessaires à l'exécution dans son environnement d'exécution.

[note de bas de page] Les implémentations doivent se comporter comme si ces phases distinctes se produisaient, bien qu'en pratique, différentes phases puissent être regroupées.

Comme l'indique le [SNIP] Les marqueurs, je n'ai pas cité toute la section, juste assez pour faire passer l'idée.

Pour souligner, les compilateurs sont no ne sont pas obligés de suivre ce modèle exact, pour autant que le résultat final soit comme s'ils l'avaient fait.

Les phases 1 à 6 correspondent plus ou moins au préprocesseur, la 7 à ce que l'on pourrait normalement considérer comme une compilation, la 8 traite des modèles et la 9 correspond à la liaison.

(Les phases de traduction de C sont similaires, mais le numéro 8 est omis).

6voto

Steve Jessop Points 166970

Les 9 "phases de la traduction" sont énumérées dans la norme à l'adresse suivante [lex.phases] (2,2 en C++11, 2,1 en C++03).

Le niveau de détail exigé dans la norme varie : le prétraitement est divisé en plusieurs phases, car il est important, à différents moments de la norme, de savoir exactement ce qui a "déjà été fait" et ce qui "reste à faire" lorsqu'un comportement particulier est défini. Ainsi, bien que la norme ne vous dise pas comment écrire un lexer, elle vous donne une feuille de route assez claire.

La liaison, quant à elle, est laissée à l'implémentation qui décide de la manière dont elle est réalisée, car la norme ne s'y intéresse pas. comment un nom donné est recherché, juste ce à quoi il se réfère.

Il ne donne pas non plus de détails sur l'analyse syntaxique, il dit simplement "Les tokens résultants sont analysés et traduits syntaxiquement et sémantiquement". C'est parce que l'ensemble des chapitres 3 à 15 sont nécessaires pour remplir ce détail.

Elle ne mentionne pas du tout les représentations internes pendant l'analyse/la traduction, ni les phases d'optimisation - elles sont importantes pour la conception des compilateurs, mais pas pour la norme. L'optimisation peut intervenir à différents endroits dans différents compilateurs. Pendant longtemps, l'optimisation était presque entièrement dans la phase de compilation, avant l'émission des fichiers objets, et les linkers étaient stupides comme tout. Je pense que maintenant les implémentations C++ sérieuses peuvent toutes faire au moins une certaine optimisation à travers plusieurs UT. Ainsi, "les autres" ne sont pas simplement laissés de côté dans la norme, ils changent réellement au fil du temps.

3voto

Liam M Points 2322

La spécification C++ est intentionnellement vague à de nombreux égards, principalement pour rester indépendante de la mise en œuvre. Un grand nombre des domaines dans lesquels le langage est vague ne sont plus une préoccupation majeure - par exemple, vous pouvez généralement compter sur un caractère de 8 bits. Cependant, d'autres questions telles que la disposition des structures qui utilisent l'héritage multiple est une réelle préoccupation, tout comme les implications des fonctions virtuelles sur les classes. Ces questions ont un impact sur la compatibilité du code généré par différents compilateurs. L'interface binaire d'application (ou ABI) du C++ n'est pas rigoureusement définie et, par conséquent, vous devez parfois plonger dans le C lorsque cela devient problématique. L'écriture d'une interface de plugin en est un bon exemple.

De même, la norme ne donne pas une description détaillée de la façon dont un compilateur doit être construit, car il existe de nombreuses décisions et caractéristiques clés qui différencient les compilateurs. Par exemple, MSVC peut effectuer des constructions partielles (permettant d'éditer et de continuer), ce que GCC ne fait pas. Cependant, de manière générale, tous les compilateurs effectuent des étapes similaires : prétraitement, analyse syntaxique, détermination du déroulement du programme, production d'une table de symboles et production d'une série linéaire d'instructions qui peuvent ensuite être liées pour produire un exécutable. Oh, et lier ces fichiers objets, ceci est généralement fait par un éditeur de liens.

J'ai jeté un bref coup d'œil, il est plutôt difficile de trouver des descriptions de compilateurs individuels. Je doute qu'il y ait beaucoup de choses sur les compilateurs commerciaux comme ceux proposés par Microsoft, pour des raisons purement commerciales. GCC est votre meilleure chance, bien que Microsoft soit heureux de décrire le processus. Il s'agit pourtant d'un sujet assez banal : les compilateurs fonctionnent tous à peu près de la même manière. Le véritable or se trouve dans la façon dont ils exécutent ces étapes, les algorithmes et les structures de données qu'ils utilisent. À cet égard, Je recommande ce livre . J'ai acheté un exemplaire tout neuf pour un cours universitaire il y a quelques années, et j'ai emprunté la plupart de mes manuels à la bibliothèque :).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X