web-dev-qa-db-fra.com

Causes courantes des bogues dans la version publiée non présents en mode débogage

Quelles sont les raisons typiques des bugs et des comportements de programme anormaux qui ne se manifestent qu'en mode compilation, mais qui ne se produisent pas en mode débogage?

59
Benny

Plusieurs fois, en mode débogage en C++, toutes les variables sont initialisées à zéro, alors que la même chose ne se produit pas en mode édition, sauf indication explicite.

Recherchez des macros de débogage et des variables non initialisées.

Votre programme utilise-t-il le threading, alors l'optimisation peut aussi causer des problèmes en mode release.

Vérifiez également toutes les exceptions, par exemple non directement liées au mode de publication, mais nous ignorons parfois certaines exceptions critiques, telles que la violation d'accès de mem dans VC++, mais cela peut poser problème au moins sous un autre système d'exploitation comme Linux, Solaris. Idéalement, votre programme ne devrait pas intercepter des exceptions critiques telles que l’accès à un pointeur NULL. 

29
Priyank Bolia

Un piège courant consiste à utiliser une expression avec un effet secondaire dans un ASSERT.

18
Henrik

D'autres différences pourraient être:

  • Dans un langage usé, le collecteur Est généralement plus agressifen mode de publication;
  • La disposition de la mémoire peut souvent être différente.
  • La mémoire peut être initialisée différemment (par exemple, elle pourrait être remise à zéro en mode débogage, ou être réutilisée de manière plus agressive en publication);
  • Les sections locales peuventbe être encouragées à enregistrer des valeurs dans la version, ce qui peut causer des problèmes avec les valeurs à virgule flottante.
9
stusmith

J'ai déjà été piqué par un certain nombre de bugs qui fonctionnaient bien dans les versions Debug mais qui plantaient dans les versions Release. Il y a beaucoup de causes sous-jacentes (y compris bien sûr celles qui ont déjà été résumées dans ce fil) et j'ai été attiré par tout ce qui suit:

  • Variables membres ou fonctions membres dans un #ifdef _DEBUG, de sorte qu'une classe ait une taille différente dans une construction de débogage. Parfois, #ifndef NDEBUG est utilisé dans une version release
  • De même, il existe un #ifdef différent qui n'est présent que dans l'une des deux versions
  • La version de débogage utilise les versions de débogage des bibliothèques système, en particulier les fonctions d'allocation de mémoire et de mémoire.
  • Fonctions en ligne dans une version release
  • Ordre d'inclusion des fichiers d'en-tête. Cela ne devrait pas causer de problèmes, mais si vous avez quelque chose comme un #pragma pack qui n'a pas été réinitialisé, cela peut entraîner de vilains problèmes. Des problèmes similaires peuvent également se produire avec des en-têtes précompilés et des inclus forcés.
  • Caches: vous pouvez avoir du code tel que des caches qui ne sont utilisés que dans les versions, ou des limites de taille de cache différentes
  • Configurations de projet: les configurations de débogage et de publication peuvent avoir des paramètres de construction différents (cela est susceptible de se produire lors de l'utilisation d'un IDE)
  • Conditions de course, problèmes de timing et effets secondaires divers résultant du code de débogage uniquement

Quelques conseils que j'ai accumulés au fil des ans pour aller au fond des bogues de débogage/libération: 

  • Essayez de reproduire un comportement anormal dans une version de débogage si vous pouvez, et même mieux, écrire un test unitaire pour le capturer.
  • Pensez à ce qui diffère entre les deux: paramètres du compilateur, caches, code de débogage uniquement. Essayez de minimiser ces différences temporairement
  • Créez une version validée avec les optimisations désactivées (pour que vous puissiez obtenir des données utiles dans le débogueur) ou une version optimisée. En minimisant les changements entre le débogage et la publication, vous aurez plus de chance d’isoler quelle différence est à l’origine du bogue.
6
the_mandrill

Oui !, si vous avez une compilation conditionnelle, il peut y avoir des bogues de synchronisation (verset à code de version optimisé, code de débogage non optimisé), une réutilisation de la mémoire et un segment de débogage.

3
Simeon Pilgrim

C'est possible, surtout si vous êtes dans le domaine C.

Une des raisons pourrait être que la version de DEBUG peut ajouter du code pour vérifier les pointeurs parasites et protéger votre code contre les plantages (ou se comporte de manière incorrecte). Si tel est le cas, vérifiez attentivement les avertissements et autres messages que vous recevez de votre compilateur.

Une autre cause pourrait être l'optimisation (normalement activée pour les versions et désactivée pour le débogage). La disposition du code et des données a peut-être été optimisée et, alors que votre programme de débogage venait, par exemple, d'accéder à de la mémoire inutilisée, la version en cours tente maintenant d'accéder à la mémoire réservée ou même de pointer du code!

EDIT: Je vois que d'autres l'ont mentionné: bien sûr, vous pourriez avoir des sections de code entières qui sont conditionnellement exclues si vous ne compilez pas en mode DEBUG. Si tel est le cas, j'espère que c'est vraiment du code de débogage et pas quelque chose de vital pour l'exactitude du programme lui-même!

3
Remo.D

Les fonctions de la bibliothèque CRT se comportent différemment dans les versions debug et release (/ MD vs/MDd).

Par exemple, les versions de débogage pré-remplissent souvent les tampons que vous passez à la longueur indiquée pour vérifier votre réclamation. Les exemples incluent strcpy_s, StringCchCopy, etc. Même si les chaînes se terminent plus tôt, votre szDest better soit n octets long!

3
Alex Budovski

Bien sûr, par exemple, si vous utilisez des constructions comme

#if DEBUG

//some code

#endif
2
Max Galkin

En .NET, même si vous n'utilisez pas de compilation conditionnelle comme #if DEBUG, le compilateur reste beaucoup plus libéral avec des optimisations en mode publication qu'en mode débogage, ce qui peut entraîner la publication de bogues uniquement.

2
Matthew Scharley

Vous auriez besoin de donner beaucoup plus d'informations, mais oui, c'est possible. Cela dépend de ce que fait votre version de débogage. Il se peut que vous ayez des traces de connexion ou des vérifications supplémentaires qui ne soient pas compilées dans une version finale. Ces chemins de code de débogage uniquement peuvent avoir des effets secondaires non souhaités qui changent d'état ou affectent les variables de manière étrange. Les versions de débogage fonctionnent généralement plus lentement, ce qui peut affecter le threading et masquer les conditions de concurrence. De même pour les optimisations simples d'une compilation de version, il est possible (même si cela est peu probable de nos jours) qu'une compilation de version puisse court-circuiter quelque chose en tant qu'optimisation.

1
blowdart

Sans plus de détails, je suppose que "pas OK" signifie qu’il ne compile pas ou ne génère pas une erreur au moment de l’exécution. Vérifiez si votre code s'appuie sur la version de compilation, via les instructions #if DEBUG ou les méthodes marquées de l'attribut Conditional.

1
Konamiman

Dans une fonction non vide, tous les chemins d'exécution doivent se terminer par une instruction return. 

En mode débogage, si vous oubliez de terminer ce chemin avec une instruction return, la fonction renvoie généralement 0 par défaut.

Cependant, en mode de publication, votre fonction peut renvoyer des valeurs parasites, ce qui peut affecter le fonctionnement de votre programme.

1
loudandclear

Il existe des optimisations du compilateur qui peuvent casser un code valide car elles sont trop agressives.

Essayez de compiler votre code avec moins d'optimisation activée.

1
Georg Schölly

Cela est possible si vous avez une compilation conditionnelle de sorte que le code de débogage et le code de version soient différents, et qu'il existe un bogue dans le code utilisé uniquement en mode de publication.

Sinon, ce n'est pas possible. Il existe des différences dans la manière dont le code de débogage et le code de version sont compilées, et dans le mode d'exécution du code, qu'il soit exécuté sous un débogueur ou non, mais si l'une de ces différences entraîne autre chose qu'une différence de performances, le problème persiste.

Dans la version de débogage, l'erreur peut ne pas se produire (parce que le temps ou l'allocation de mémoire sont différents), mais cela ne signifie pas que l'erreur n'est pas là. Il peut également y avoir d'autres facteurs non liés au mode débogage qui modifient le minutage du code, causant ou non l'erreur, mais tout se résume au fait que si le code était correct, l'erreur ne se produirait pas dans l'une des situations.

Donc, non, la version de débogage n’est pas correcte simplement parce que vous pouvez l’exécuter sans erreur. Si une erreur se produit lorsque vous l'exécutez en mode de publication, ce n'est pas à cause du mode de publication, mais bien parce que l'erreur était présente depuis le début.

1
Guffa

Je me souviens de la construction de dll et de pdb en c/c ++. 

Je me rappelle de ça:

  • L'ajout de données de journal peut parfois provoquer le déplacement ou la disparition du bogue ou faire apparaître une autre erreur (ce n'était donc pas vraiment une option).
  • Beaucoup de ces erreurs étaient dues à l'attribution de caractères dans strcpy et strcat et aux tableaux de caractères [] etc ... 
  • Nous en avons éliminé quelques-uns en exécutant le vérificateur de limites et en résolvant simplement les problèmes de mémoire d'allocation/désallocation
  • Plusieurs fois, nous avons systématiquement examiné le code et fixé une allocation de caractère (comme dans tous les fichiers). 
  • En définitive, il s’agit d’un problème d’allocation et de gestion de la mémoire, ainsi que des contraintes et des différences entre les modes Debug et Release.

Et puis espéré pour le mieux.

Parfois, je livrais temporairement des versions de débogage de DLL aux clients, afin de ne pas retarder la production, tout en travaillant sur ces bugs.

0
Sassine Jaoude

Je venais de faire l'expérience de cela lorsque j'appelais une fonction d'assemblage qui ne restaurait pas les valeurs précédentes des registres. 

Dans la configuration "Release", VS compilait avec/O2, ce qui optimise le code pour la vitesse. Ainsi, certaines variables locales étaient simplement mappées sur des registres de la CPU (pour l’optimisation) qui étaient partagés avec la fonction susmentionnée, entraînant une grave corruption de la mémoire.

Quoi qu'il en soit, voyez si vous ne jouez pas indirectement avec les registres de la CPU où que ce soit dans votre code.

0
mycelo

C'est possible. Si cela se produit et qu'aucune compilation conditionnelle n'est impliquée, vous pouvez être à peu près sûr que votre programme est faux et qu'il fonctionne en mode débogage uniquement à cause d'initialisations mémoire fortuites ou même de la mise en page en mémoire!

0
UncleZeiv

Une autre raison pourrait être les appels à la base de données . Enregistrez-vous et mettez-vous à jour le même enregistrement plusieurs fois dans le même thread, Parfois pour la mise à jour . Lors du traitement et de la mise à jour, l’appel de la base de données n’a trouvé aucun enregistrement . Cela ne se produira pas dans le débogage car le débogueur s’assure de terminer toutes les tâches en attente avant l’atterrissage.

0
Pratyush Dhanuka