Dans quelles circonstances un lieur C éliminera-t-il les symboles volatiles inutilisés?

J’utilise une chaîne d’outils très spécifique (processeur SHARC DSP d’Analog Devices) et j’aimerais mieux comprendre mon compilateur / éditeur de liens.

J’ai quelque part une variable globale volatile:

volatile long foo; 

Cette variable n’est ni utilisée ni référencée dans mon code mais je souhaite la conserver dans mon exécutable final (ne me demandez pas pourquoi, la sortingste vérité est sortingste).

Je lie généralement mon projet avec l’option -e . Il indique à l’éditeur de liens de supprimer le code mort de l’exécutable. Au départ, je pensais qu’aucun compilateur n’oserait supprimer une variable globale, en particulier si ces symboles sont déclarés volatils. Malheureusement, c’est le cas.

Ensuite, j’ai trouvé un pragma très spécifique #pragma retain_name qui indique à l’éditeur de liens de conserver un symbole même s’il n’est jamais utilisé.

Je voudrais savoir si une telle situation peut être trouvée dans certaines normes ISO / POSIX. J’ai toujours pensé que ni le compilateur ni l’éditeur de liens ne pouvaient présumer de symboles volatiles. Et ainsi, aucun compilateur n’essaierait jamais de supprimer une variable ou fonction volatile morte de l’exécutable final.

Ai-je tort?

Si une norme pour C est le livre K & R, il n’ya pas grand chose à dire à propos de volatile sauf qu’il est mentionné à quelques resockets et qu’il serait lié à l’optimisation.

Dans l’Annexe A.8.2, les spécificateurs de type, on peut lire ceci:

Les types peuvent également être qualifiés pour indiquer les propriétés spéciales des objects déclarés. type-qualifier: const volatile Les qualificateurs de type peuvent apparaître avec n’importe quel spécificateur de type. Un object const peut être initialisé, mais pas ensuite atsortingbué à. Il n’y a pas de sémantique dépendant de l’implémentation pour les objects volatiles. Les propriétés const et volatile sont nouvelles avec la norme ANSI. Le but de const est d’annoncer les objects pouvant être placés en mémoire en lecture seule et peut-être d’augmenter les possibilités d’optimisation. Le but de volatile est de forcer une implémentation à supprimer l’optimisation qui pourrait autrement se produire. Par exemple, pour une machine avec une entrée / sortie mappée en mémoire, un pointeur sur un registre de périphérique peut être déclaré en tant que pointeur sur volatile, afin d’empêcher le compilateur de supprimer les références apparemment redondantes via le pointeur. Sauf qu’il doit diagnostiquer les tentatives explicites de modification des objects const, un compilateur peut ignorer ces qualificateurs.

Soulignez le mien et notez ce que dit le dernier paragraphe. Cela pourrait suggérer que le compilateur peut choisir d’ignorer le qualificatif volatile toute façon.

Les compilateurs permettront aux variables volatiles de ne pas être optimisées, même si elles ne sont jamais utilisées. Je ne suis pas si sûr sur les linkers cependant. La norme en dit très peu sur le processus de liaison.

D’après mon expérience générale avec les compilateurs commerciaux pour les cibles intégrées, ils ne respectent parfois pas totalement les normes. J’utilise depuis peu une chaîne d’outils du compilateur TI et de l’éditeur de liens, et disons simplement que c’est vraiment différent de ce à quoi je suis habitué avec les ports gcc + ld pour ARM, par exemple …

MODIFIER:

Non, bien sûr, le livre K & R n’est pas la norme. Jetons un coup d’oeil à une norme réelle, par exemple la norme ISO C99 obtenue à partir d’ ici , un paragraphe de la Section 6.7.3 Type qualifiers, 6 dit:

Un object de type qualifié volatile peut être modifié de manière inconnue de l’implémentation ou avoir d’autres effets secondaires inconnus. Par conséquent, toute expression faisant référence à un tel object doit être évaluée ssortingctement selon les règles de la machine abstraite, telles que décrites au 5.1.2.3. De plus, à chaque sharepoint la séquence, la dernière valeur stockée dans l’object doit concorder avec celle prescrite par la machine abstraite, à l’exception des modifications telles que modifiées par les facteurs inconnus mentionnés précédemment. -défini .

Malheureusement, je ne pense pas que cela aide à répondre à la question ..

Vous pouvez créer une fonction fictive avec une liaison externe qui utilise la variable.

 long help_us_keep_foo(void) { return foo; } 

Si vous n’effectuez pas une parsing complète du programme, cela empêchera l’élimination de foo . Si vous effectuez une parsing complète du programme, vous pouvez utiliser une astuce comme celle-ci.

 int main(int argc, char * * argv) { if (getenv("PRINT_THE_VALUE_OF_FOO_AT_PROGRAM_STARTUP")) printf("Your hovercraft is full of eels, and foo is %ld\n", foo); /* Do whatever your program has to do... */ return 0; } 

J’ai utilisé une astuce similaire (insérer des instructions d’impression inoffensives qui testent une condition exceptionnellement improbable) dans le code d’parsing comparative afin de m’assurer que les éléments que je voulais parsingr ne sont pas optimisés.

Si la situation le permet, vous pouvez utiliser un truc moins «visible» comme assigner foo = foo mais comme il est volatile , je ne suis pas sûr que vous puissiez le faire en toute sécurité.