Ce document est à la fois un pense-bête de paramétrages pour les options de compilations, et une petite explication sur chacune. Je n'explique malheureusement pas tellement ce que l'on peut faire avec. J'essaierais d'écrire d'autre documents à l'avenir, mais pour ce genre d'information, vous devrez vous pour l'instant vous contenter de chercher ailleurs.
Dans la phase de compilation et link, des symboles de debug peuvent être généré. Avec Visual C++ 6 et 2003, ils vont dans des fichiers .pdb. Pour les configuration Debug tout est automatiquement mis par les environnements de développement, mais pas pour les configurations Release. Alors bien sûr ce n'est pas indispensable pour tout, mais ça l'est pour une grande quantité de cas, comme par exemple les suivants :
Vous pouvez aussi générer des fichiers .map. Ils sont, eux, en mode texte, et représentent la cartographie de votre exécutable (ou dll). Lorsqu'ils sont généré de façon complète, ils permettent :
Remarque importante : Les paramétrages dont je parle ici ne changent pas les performances : ils permettent juste de générer ces fichiers .pdb et .map complets. Je met dans certaines remarques à part des paramètres qui, eux, pourrait les changer.
Autre Remarque importante : Il ne faut surtout pas oublier que les fichiers .pdb complets contiennent des informations détaillées sur votre code : avec un exécutable et son .pdb, on pourrait reconstruire du code C++ presque lisible. Selon votre mode de licence utilisateur, vous souhaiterez peut-être plutôt garder ces fichiers pour vous. Par contre, Visual Studio 2003 permet maintenant de générer des fichiers .pdb "allégés" ne contenant que les informations publiques. Microsoft met ces fichiers de symboles "publiques" à la disposition de tout le monde via ses serveurs de symboles (cf ma page qui indique comment les configurer).
Générer ces fichers .pdb/.map rentre dans une méthodologie générale de build dont je ne parle que très succinctement ici (ce n'est pas le but de ce document) :
Il s'agit juste d'un petit conseil dont vous pouvez faire ce que vous voulez.
Si vous avez plusieurs projet, je vous suggère de générer leur résultat dans des
répertoire communs à tout les projets. Par exemple, si dans votre arborescence, vous
avez un premier répertoire, puis un répertoire par projet, configurez les projets pour
qu'ils génèrent leur résultat dans un répertoire comme ..\BinDebug pour la
version Debug, et ..\BinRelease pour la version Release.
Pour ce faire, c'est quasiment la même explication avec Visual Studio 6 et 2003 :
il vous suffit d'aller dans les settings (ou properties pour VS 2003)
de votre projet, et de mettre dans l'onglet general et la zone Output Files la
valeur souhaitée, et ce, dans chaque configuration (release, debug...).
Ce n'est pas vraiment le sujet de ce texte, mais on pourrait l'inclure dans une méthodologie plus générale de build. Si vous êtes dans un projet ATL, le Wizard vous a généré tout une tripoté de configurations :
Je vous suggère déjà d'enlever les deux configurations MinSize, car elles génèrent une dépendance à atl.dll, ce qui vous oblige à le déployer - et dans la bonne version... Bref - que des ennuis. Ensuite, si vous savez que dans votre projet, vous n'avez besoin que d'Unicode (dans les composants serveurs par exemple) ou bien que d'ANSI (dans des composants devant fonctionner sur Windows 9x/ME), enlevez celles dont vous n'avez pas besoin : elles vous gênerons plus qu'autre chose, et vous pourrez toujours les recréer en prenant exemple sur un projet généré de zéro.
Bon, voici donc les différentes cases à cocher pour générer votre .pdb et .map, ainsi que pour quelques autre choses (précisées à chaque étape). Je met des captures d'écran aux endroits importants
Donc allez tout d'abord à la racine de votre projet, puis faite un clic droit puis
settings. Dans la combobox Setting For sélectionnez toutes les
configurations Release. Allez ensuite dans l'onglet C/C++, puis dans la
General. Ensuite, sélectionnez Program Database dans la
combobox Debug Info.
Voici une capture d'écran de ce que vous pourriez avoir :
Petite remarque au passage : ceci peut par contre changer les performances, contrairement à ma remarque du début. Je vous suggère de mettre l'option d'optimisation Minimize Size, plutôt que Maximize Speed. En effet, la littérature et les faits indiquent :
(fin de la Petite remarque au passage...)
- En produisant des exécutables plus petits, on a plus de chance de garder des portions de code dans la mémoire cache, et même tout simplement en mémoire physique, et si c'est le cas, de générer finalement du code bien plus rapide.
- L'option Maximize Speed contient l'option Frame-Pointer Omission qui peut certes optimiser, mais qui est relativement gênante pour certains scénario de debugging : par exemple, si vous développez une librairie et que la personne qui utilise votre librairie n'a pas le .pdb, elle risque d'avoir des piles invalides en traversant votre code, ou encore, si vous souhaitez utiliser des outils comme umdh, pour détecter les memory leak, vous ne verrez pas les piles complètes, etc.
- C'est peut-être devenu faux avec les derniers services pack de Visual C++ 6, mais il a été dit par le passé que l'option Maximize Speed générait parfois du code invalide. (a prendre donc avec des pincettes).
Ensuite, dans l'onglet Link, dans la catégorie General, cochez les cases
Generate debug info et Generate map file.
Voici une capture d'écran de
ce que vous pourriez avoir :
Si vous avez utilisé mon petit conseil ci-dessus, le .map sera malheureusement généré dans
le mauvais répertoire. Restez donc dans l'onglet Link, et allez dans la catégorie
Debug pour mettre dans la zone Mapfile name le bon répertoire : par exemple,
..\BinRelease\.....
Voici une capture d'écran de ce que vous pourriez avoir :
Il y a ensuite des options supplémentaires à rajouter à la main, toujours dans l'onglet Link,
dans la catégorie General, dans la zone Project options. Rajouter alors les quatres
options /OPT:REF /MAPINFO:EXPORTS /MAPINFO:LINES /RELEASE. Pour la première, lisez la documentation
pour être sûr qu'elle convient à votre projet (vous avez peut-être des pragmas
bizarres qui pourraient le contre-
indiquer, mais je ne vois pas bien dans quel cas). Les options commençant par MAP servent à avoir
un fichier map complet (avec même les numéros de lignes !!!). L'option /RELEASE sert à générer un
checksum dans votre fichier exécutable. Si vous ne le mettez pas, vous aurez un warning à chaque fois que vous
ouvrirez votre exécutable (ou un crash dump) via les outils de debugging (en tout cas au moins sous WinDBG).
En plus, ce warning pourrait être justifié si vous avez fait des mélanges entre vos .exe/.dll et vos .pdb.
Voici une capture d'écran de ce que vous pourriez avoir :
Le point suivant concerne les dll, et à vrai dire, plutôt les composants serveurs, car dans ces
environnements, on connait toutes les dll chargées par les processus.
Donc dans les dll, je vous suggère de choisir une adresse de base par défaut, et surtout, d'en
choisir une différente pour toutes vos dll chargées. Ceci a principalement deux avantages.
Tout d'abord, le chargement d'une dll par windows est plus rapide si celui-ci n'a pas besoin
de la reloger (cherchez ce terme sur google pour plus d'explications : en gros, ajouter une valeur
à tout les endroits du code et des données dépendant de l'adresse de chargement). Le deuxième
avantage est que si vous avez un crash dans lequel vous ne connaissez que l'adresse ou que vous
n'avez qu'un fichier drwtsn32.log (et pire, s'il généré sous Windows 2000 car ceux de Windows XP/2003
sont plus verbeux) pour vous donner des adresses, et seulement ça, vous n'aurez pas à lancer les dés
pour savoir quelle dll est fautive.
Donc pour choisir cette adresse de chargement, restez dans l'onglet Link, dans la catégorie
output, et mettez une adresse dans Base address. Vous devriez ensuite vérifier par
la suite, sur une machine ressemblant à votre machine cible "typique", si votre dll n'est pas relogée,
via, par exemple, l'outil Process Explorer
de Sysinternals.
Voici une capture d'écran que vous pourriez avoir :
Visual C++ 2003 est bien plus arrangeant que le 6 : beaucoup d'options sont déjà bien mises,
et il ne faut pas mettre d'option à la main, dans la ligne de commande.
Je repasse dessus en supposant que vous avez lu le paragraphe sur Visual C++ 6 : mais je renvoie dessus quand
j'y fait expressément référence.
Donc tout d'abord, il faut aller dans les properties, puis choisir comme configuration
courante la Release. Ensuite, dans la rubrique C/C++, puis General, il faut s'assurer que
l'option Debug Information Format est à Program Database (/Zi).
Voici une capture d'écran que vous pourriez avoir :
Ensuite, toujours dans la rubrique dans la sous rubrique C/C++, puis dans optimisation, il est parfois conseillé de changer le mode d'optimisation - je fais ici une remarque semblable à celle de Visual C++ 6, mais adaptée à Visual C++ 2003 :
Remarque : ceci peut par contre changer les performances, contrairement à ma remarque du début. Il est parfois conseillé de mettre l'option d'optimisation Minimize Size (/O1), plutôt que Maximize Speed (/O2). En effet, la litérature et les faits indiquent :
- En produisant des exécutables plus petits, on a plus de chance de garder des portions de code dans la mémoire cache, et même tout simplement en mémoire physique, et si c'est le cas, de générer finalement du code bien plus rapide.
- Il est mentionné que Microsoft utilise cette option pour ses Builds.
Ensuite, dans la rubrique Linker, puis Debugging, il faut mettre trois option à
Yes : Generate Debug Info, Generate Map File, Map Exports, et
Map Lines. Avec cette version, vous pouvez aussi générer un fichier .pdb allégé, ne contenant que
des symboles publiques. En effet, si vous souhaitez distribuer vos .pdb, il ne faut pas oublier qu'ils
contiennent des informations très détaillées sur votre code : avec un exécutable et son .pdb, on pourrait
reconstruire du code C++ presque lisible. Vous pouvez donc ici utiliser l'option
Strip Private Symbols, pour générer un .pdb "light", qui contient moins d'informations.
Voici une capture d'écran que vous pourriez avoir :
Ensuite, toujours dans la rubrique Linker, dans Optimization, il faut vérifier que les
options Reference et Enable COMDAT Folding sont respectivement à
Eliminate Unreferenced Data (/OPT:REF) et Remove Redundant COMDATs (/OPT:ICF) cf les documentations,
et aussi la remarque que je met ci-dessus pour Visual C++ 6.
Voici une capture d'écran que vous pourriez avoir :
Et pour la même raison que le /RELEASE mis à la main pour Visual C++ 6 ci-dessus,
il faut, ici, dans Visual C++ 2003, cocher la case Set Checksum, dans la rubrique Linker puis
Advanced.
Voici une capture d'écran que vous pourriez avoir :
Le point suivant concerne les dll, et je vais vous renvoyer à l'explication plus détaillée que
je donne ci-dessus. Pour rappel, il est préférable de choisir une adresse de base par défaut
pour toutes vos dll, et bien sûr, d'en choisir une différente pour chacune d'entre-elles.
Pour choisir l'adresse par défaut, il faut la fixer dans Base address.
Voici une capture d'écran que vous pourriez avoir (avec ici une adresse à 0x2B000000 pour cette
dll - et je le rappelle, uniquement pour elle) :
Ensuite, si vous ne l'avez pas déjà fait, je vous invite à configurer vos outils de développement pour qu'ils téléchargent automatiquement les symboles publiques de Windows chez Microsoft : pour cela, allez sur ma page décrivant comment faire.
Sinon, pour l'instant j'ai fait ce document comme un pense-bête, mais avec quand même par mal d'explications. Ensuite, on peut faire beaucoup de choses dont j'évoque certaines ci-dessus (sans tellement les expliquer : j'essaierais de faire de nouveaux documents orientés dans ces directions). Dans l'immédiat, je vous renvoie plutôt aux liens cités, et aussi à google pour faire le reste.
Je voudrais tout de même citer un Livre qui pourrais vous intéresser : il s'agit de "Debugging Applications for Microsoft .Net and Microsoft Windows", de John Robbins. Vous Pouvez le trouver sur Amazon.fr et sûrement aussi dans des librairies spécialisées.
![]() |
retour page informatique |
retour page principale |