Le programme se bloque uniquement en tant que version de version - comment déboguer?

95

J'ai un problème de type "Schroedinger's Cat" ici - mon programme (en fait la suite de tests de mon programme, mais un programme néanmoins) plante, mais uniquement lorsqu'il est construit en mode release, et uniquement lorsqu'il est lancé à partir de la ligne de commande . Grâce au débogage de l'homme des cavernes (c'est-à-dire, des messages printf () désagréables partout), j'ai déterminé la méthode de test où le code se bloque, bien que malheureusement le crash réel semble se produire dans un destructeur, puisque les derniers messages de trace que je vois sont dans d'autres destructeurs qui s'exécutent proprement.

Lorsque j'essaye d'exécuter ce programme dans Visual Studio, il ne plante pas. Il en va de même lors du lancement à partir de WinDbg.exe. Le plantage se produit uniquement lors du lancement à partir de la ligne de commande. Cela se produit sous Windows Vista, btw, et malheureusement je n'ai pas accès à une machine XP pour le moment pour tester.

Ce serait vraiment bien si je pouvais demander à Windows d'imprimer une trace de pile, ou quelque chose d' autre que de simplement terminer le programme comme s'il s'était terminé proprement. Quelqu'un a-t-il des conseils sur la façon dont je pourrais obtenir des informations plus significatives ici et, espérons-le, corriger ce bogue?

Edit: Le problème était en effet causé par un tableau hors limites, que je décris plus en détail dans cet article . Merci à tous pour votre aide à trouver ce problème!

Nik Reiman
la source
Pouvez-vous donner un exemple de cette méthode de test?
akalenuk
Non désolé, le code est beaucoup trop complexe pour être facilement collé ici, et comme je l'ai mentionné, cela ne se produit pas dans la méthode de test elle-même, mais plutôt dans un destructeur par la suite. Il n'y a cependant pas de pointeurs non initialisés ou quoi que ce soit de ce genre dans cette méthode.
Nik Reiman
3
La plupart des réponses ne sont guère plus que des suppositions. Il existe quelques techniques courantes pour analyser les versions de version qui plantent sans attacher de débogueur: stackoverflow.com/a/18513077/214777?stw=2
Sebastian
Ce n'est peut-être pas de votre faute: le niveau d'optimisation -O3 est-il dangereux dans g ++?
Brent Bradburn

Réponses:

127

Dans 100% des cas que j'ai vus ou entendus, où un programme C ou C ++ s'exécute correctement dans le débogueur mais échoue lorsqu'il est exécuté à l'extérieur, la cause a été l'écriture au-delà de la fin d'un tableau local de fonction. (Le débogueur en met plus sur la pile, vous êtes donc moins susceptible d'écraser quelque chose d'important.)

James Curran
la source
31
Quelqu'un a donné un cigare à cet homme! Dans mon cas, je passais un StringBuilder qui n'avait pas une capacité assez grande à une fonction P / Invoke. Je suppose que c'est comme quelqu'un qui écrit sur votre visage avec un marqueur magique lorsque vous dormez: sous le débogueur, ils finissent par gribouiller sur votre front, donc vous ne le remarquez pas, mais sans le débogueur, ils finissent par vous poignarder dans le oeil ... quelque chose comme ça. Merci pour cette astuce!
Nicholas Piasecki
1
Dans mon cas, il s'est avéré être un problème d'alignement sur un processeur ARM utilisant Obj-C.
Almo
1
11 ans plus tard et cela sonne toujours vrai ... n'oubliez pas de réserver vos vecteurs.
dav
1
ok, alors comment changer le comportement du mode débogage pour pouvoir déboguer réellement.
Paul Childs
1
«Maintenant savoir où chercher» mais comment tout fonctionne dans le débogage vous indique où se trouve le problème. Bien que je pense que votre réponse est correcte dans la plupart des cas, et savoir ce qu'il faut rechercher est un bon début, traîner à travers une grande base de code pour identifier exactement où se trouve le problème peut être d'un coût prohibitif.
Paul Childs
55

Lorsque j'ai rencontré des problèmes comme celui-ci auparavant, cela était généralement dû à l'initialisation de variables. En mode débogage, les variables et les pointeurs sont automatiquement initialisés à zéro, mais pas en mode version. Par conséquent, si vous avez un code comme celui-ci

int* p;
....
if (p == 0) { // do stuff }

En mode débogage, le code dans if n'est pas exécuté mais en mode release p contient une valeur indéfinie, qui est peu susceptible d'être 0, donc le code est exécuté provoquant souvent un crash.

Je vérifierais votre code pour les variables non initialisées. Cela peut également s'appliquer au contenu des tableaux.

David Dibben
la source
Les cas typiques oublient de placer une variable membre dans (l'une des) liste d'initialisation des membres du constructeur. A le même effet, mais il est plus difficile à trouver si vous ne savez pas que vous devez également rechercher une initialisation de membre appropriée.
steffenj
1
En mode débogage, les variables sont généralement initialisées avec une «constante définie par le compilateur» qui peut être utilisée dans le débogage pour indiquer dans quel état se trouve la variable. Par exemple: les pointeurs NULL ou 0xDeadBeef sont populaires.
Martin York
Les runtimes de débogage initialisent généralement la mémoire à une valeur différente de zéro, en particulier pour que les tests de pointeur NULL amènent le code à agir comme si le pointeur n'était pas NULL. Sinon, vous avez du code qui s'exécute correctement en mode débogage qui plante le mode de sortie.
Michael Burr
1
Non, les variables ne sont pas du tout initialisées et il est toujours UB de les «utiliser» jusqu'à ce qu'elles soient affectées. Cependant, le contenu de la mémoire sous-jacente est souvent pré-rempli avec 0x0000000 ou 0xDEADBEEF ou d'autres modèles reconnaissables.
Courses de légèreté en orbite le
26

Aucune réponse jusqu'à présent n'a tenté de donner un aperçu sérieux des techniques disponibles pour le débogage des applications de version:

  1. Les versions Release et Debug se comportent différemment pour de nombreuses raisons. Voici un excellent aperçu. Chacune de ces différences peut provoquer un bogue dans la version Release qui n'existe pas dans la version Debug.

  2. La présence d'un débogueur peut également modifier le comportement d'un programme , à la fois pour les versions de version et de débogage. Voyez cette réponse. En bref, au moins le débogueur Visual Studio utilise automatiquement le tas de débogage lorsqu'il est attaché à un programme. Vous pouvez désactiver le tas de débogage à l'aide de la variable d'environnement _NO_DEBUG_HEAP. Vous pouvez le spécifier dans les propriétés de votre ordinateur ou dans les paramètres du projet dans Visual Studio. Cela pourrait rendre le crash reproductible avec le débogueur attaché.

    Plus d'informations sur le débogage de la corruption du tas ici.

  3. Si la solution précédente ne fonctionne pas, vous devez intercepter l'exception non gérée et attacher un débogueur post-mortem à l'instance où le crash se produit. Vous pouvez utiliser par exemple WinDbg pour cela, des détails sur les débogueurs post-mortem disponibles et leur installation sur MSDN

  4. Vous pouvez améliorer votre code de gestion des exceptions et s'il s'agit d'une application de production, vous devez:

    une. Installez un gestionnaire de terminaison personnalisé à l'aide destd::set_terminate

    Si vous souhaitez déboguer ce problème localement, vous pouvez exécuter une boucle sans fin à l'intérieur du gestionnaire de terminaison et envoyer du texte à la console pour vous avertir de l' std::terminateappel. Ensuite, attachez le débogueur et vérifiez la pile d'appels. Ou vous imprimez la trace de pile comme décrit dans cette réponse.

    Dans une application de production, vous souhaiterez peut-être envoyer un rapport d'erreur à la maison, idéalement avec un petit vidage de la mémoire qui vous permet d'analyser le problème comme décrit ici.

    b. Utilisez le mécanisme de gestion des exceptions structuré de Microsoft qui vous permet de détecter les exceptions matérielles et logicielles. Voir MSDN . Vous pouvez protéger certaines parties de votre code en utilisant SEH et utiliser la même approche qu'en a) pour déboguer le problème. SEH donne plus d'informations sur l'exception qui s'est produite que vous pouvez utiliser lors de l'envoi d'un rapport d'erreur à partir d'une application de production.

Sébastien
la source
16

Choses à surveiller:

Dépassements de tableau - le débogueur de Visual Studio insère un remplissage qui peut arrêter les plantages.

Conditions de concurrence - avez-vous plusieurs threads impliqués si oui, une condition de concurrence n'apparaîtra que lorsqu'une application est exécutée directement.

Liaison - votre version de version extrait-elle les bonnes bibliothèques.

Choses à essayer:

Minidump - vraiment facile à utiliser (il suffit de le rechercher dans msdn) vous donnera un vidage sur incident complet pour chaque thread. Vous chargez simplement la sortie dans Visual Studio et c'est comme si vous déboguiez au moment du crash.

morechilli
la source
1
Salut - J'ai eu un vote anonyme sur cette réponse. J'aimerais comprendre pourquoi?
morechilli
12

Vous pouvez définir WinDbg comme débogueur post-mortem. Cela lancera le débogueur et l'attachera au processus lorsque le crash se produit. Pour installer WinDbg pour le débogage post-mortem, utilisez l'option / I (notez qu'elle est en majuscule ):

windbg /I

Plus de détails ici .

Quant à la cause, c'est très probablement une variable unifiée comme le suggèrent les autres réponses.

Franci Penov
la source
2
Et n'oubliez pas que vous pouvez demander au compilateur de générer des fichiers PDB même pour les versions de version, bien que ce ne soit pas la valeur par défaut.
Michael Burr
La seule vraie réponse à la question vraiment.
Sebastian
10

Après de nombreuses heures de débogage, j'ai finalement trouvé la cause du problème, qui était en effet causé par un dépassement de mémoire tampon, provoquant une différence d'un octet:

char *end = static_cast<char*>(attr->data) + attr->dataSize;

Il s'agit d'une erreur fencepost (erreur off-by-one) et a été corrigée par:

char *end = static_cast<char*>(attr->data) + attr->dataSize - 1;

Ce qui est étrange, c'est que j'ai mis plusieurs appels à _CrtCheckMemory () autour de différentes parties de mon code, et ils ont toujours renvoyé 1. J'ai pu trouver la source du problème en plaçant "return false;" appels dans le scénario de test, puis finalement déterminer par essais et erreurs où était la faute.

Merci à tous pour vos commentaires - j'ai beaucoup appris sur windbg.exe aujourd'hui! :)

Nik Reiman
la source
8
Aujourd'hui, j'ai débogué un problème similaire et _CrtCheckMemory () retournait toujours 1. Mais ensuite j'ai réalisé pourquoi: en mode Release, _CrtCheckMemory est # défini comme ((int) 1).
Brian Morearty
7

Même si vous avez construit votre exe en tant que version de version, vous pouvez toujours générer des fichiers PDB (base de données de programme) qui vous permettront d'empiler la trace et d'effectuer une quantité limitée d'inspection de variables. Dans vos paramètres de construction, il existe une option pour créer les fichiers PDB. Activez-le et reconnectez-le. Ensuite, essayez d'abord d'exécuter à partir de l'IDE pour voir si vous obtenez le plantage. Si c'est le cas, tant mieux - vous êtes prêt à regarder les choses. Sinon, lors de l'exécution à partir de la ligne de commande, vous pouvez effectuer l'une des deux opérations suivantes:

  1. Exécutez EXE et avant le blocage, effectuez une connexion au processus (menu Outils sur Visual Studio).
  2. Après le plantage, sélectionnez l'option pour lancer le débogueur.

Lorsqu'on vous demande de pointer vers des fichiers PDB, recherchez-les. Si les PDB ont été placés dans le même dossier de sortie que votre EXE ou DLL, ils seront probablement récupérés automatiquement.

Les PDB fournissent un lien vers la source avec suffisamment d'informations sur les symboles pour permettre de voir les traces de pile, les variables, etc. Vous pouvez inspecter les valeurs comme d'habitude, mais sachez que vous pouvez obtenir de fausses lectures car la passe d'optimisation peut signifier des choses seulement apparaissent dans les registres ou les choses se passent dans un ordre différent de celui auquel vous vous attendez.

NB: je suppose ici un environnement Windows / Visual Studio.

Greg Whitfield
la source
3

Des plantages comme celui-ci sont presque toujours dus au fait qu'un IDE définira généralement le contenu d'une variable non initialisée sur des zéros, null ou une autre valeur `` sensible '', alors que lors de l'exécution en mode natif, vous obtiendrez les déchets aléatoires que le système ramassera.

Votre erreur est donc presque certainement que vous utilisez quelque chose comme vous utilisez un pointeur avant qu'il n'ait été correctement initialisé et que vous vous en tiriez dans l'EDI car il ne pointe aucun endroit dangereux - ou la valeur est gérée par votre vérification des erreurs - mais en mode version, cela fait quelque chose de méchant.

Cruachan
la source
3

Afin d'avoir un vidage sur incident que vous pouvez analyser:

  1. Générez des fichiers pdb pour votre code.
  2. Vous rebasez pour que votre exe et vos dll soient chargés à la même adresse.
  3. Activer le débogueur post mortem tel que Dr. Watson
  4. Vérifiez l'adresse des échecs de crash à l'aide d'un outil tel que le crash finder .

Vous devriez également consulter les outils dans les outils de débogage pour Windows . Vous pouvez surveiller l'application et voir toutes les exceptions de la première chance antérieures à votre exception de la deuxième chance.

J'espère que ça aide...

Yuval Peled
la source
3

Un excellent moyen de déboguer une erreur comme celle-ci consiste à activer les optimisations pour votre build de débogage.

Mgill404
la source
2

Une fois, j'ai eu un problème lorsque l'application se comportait de la même manière que la vôtre. Il s'est avéré être un mauvais dépassement de tampon dans sprintf. Naturellement, cela fonctionnait lorsqu'il était exécuté avec un débogueur attaché. Ce que j'ai fait, c'était d'installer un filtre d'exception non géré ( SetUnhandledExceptionFilter ) dans lequel j'ai simplement bloqué indéfiniment (en utilisant WaitForSingleObject sur un faux handle avec une valeur de délai d'expiration INFINITE).

Ainsi, vous pourriez quelque chose du genre:

long __stdcall MyFilter (EXCEPTION_POINTERS *)
{
    HANDLE hEvt = :: CreateEventW (0,1,0,0);
    si (hEvt)
    {
        if (WAIT_FAILED == :: WaitForSingleObject (hEvt, INFINITE))
        {
            // échec du journal
        }
    }

}
// quelque part dans votre wmain / WinMain:
SetUnhandledExceptionFilter (MyFilter);

J'ai ensuite attaché le débogueur après que le bug se soit manifesté (le programme gui a cessé de répondre).

Ensuite, vous pouvez effectuer un vidage et l'utiliser plus tard:

.dump / ma path_to_dump_file

Ou déboguez-le tout de suite. Le moyen le plus simple consiste à suivre où le contexte du processeur a été enregistré par la machine de gestion des exceptions d'exécution:

Gamme sd esp 1003f

La commande recherchera dans l'espace d'adressage de la pile les enregistrements CONTEXT selon la longueur de la recherche. J'utilise généralement quelque chose comme «l? 10000» . Remarque: n'utilisez pas de nombres inhabituellement élevés car l'enregistrement que vous recherchez est généralement proche du cadre de filtre d'exception non géré. 1003f est la combinaison de drapeaux (je crois que cela correspond à CONTEXT_FULL) utilisé pour capturer l'état du processeur. Votre recherche ressemblerait à ceci:

0: 000> sd esp l1000 1003f
0012c160 0001003f 00000000 00000000 00000000? ...............

Une fois que vous obtenez les résultats, utilisez l'adresse dans la commande cxr:

.cxr 0012c160

Cela vous mènera à ce nouveau CONTEXTE, exactement au moment du crash (vous obtiendrez exactement la trace de la pile au moment où votre application s'est plantée). De plus, utilisez:

.exr -1

pour savoir exactement quelle exception s'est produite.

J'espère que ça aide.

juger
la source
2

Cela se produit parfois parce que vous avez encapsulé une opération importante dans la macro "assert". Comme vous le savez peut-être, "assert" évalue les expressions uniquement en mode débogage.

Mohamad mehdi Kharatizadeh
la source
1

En ce qui concerne vos problèmes pour obtenir des informations de diagnostic, avez-vous essayé d'utiliser adplus.vbs comme alternative à WinDbg.exe? Pour vous attacher à un processus en cours, utilisez

adplus.vbs -crash -p <process_id>

Ou pour démarrer l'application dans le cas où le crash se produirait rapidement:

adplus.vbs -crash -sc your_app.exe

Des informations complètes sur adplus.vbs sont disponibles à l' adresse : http://support.microsoft.com/kb/286350

DocMax
la source
1

Ntdll.dll avec le débogueur attaché

Une petite différence entre le lancement d'un programme à partir de l'IDE ou de WinDbg par opposition à son lancement à partir de la ligne de commande / du bureau est que lors du lancement avec un débogueur attaché (c'est-à-dire IDE ou WinDbg) ntdll.dll utilise une implémentation de tas différente qui effectue une petite validation sur l'allocation / la libération de mémoire.

Vous pouvez lire certaines informations pertinentes dans le point d'arrêt utilisateur inattendu dans ntdll.dll . PageHeap.exe est un outil qui pourrait vous aider à identifier le problème .

Analyse de crash

Vous n'avez pas écrit quel est le "crash" que vous rencontrez. Une fois que le programme plante et vous propose d'envoyer les informations d'erreur à Microsoft, vous devriez pouvoir cliquer sur les informations techniques et vérifier au moins le code d'exception, et avec un peu d'effort, vous pouvez même effectuer une analyse post-mortem (voir Heisenbug : Le programme WinApi plante sur certains ordinateurs) pour obtenir des instructions)

Suma
la source
1

Vista SP1 a en fait un très bon générateur de vidage sur incident intégré au système. Malheureusement, il n'est pas activé par défaut!

Consultez cet article: http://msdn.microsoft.com/en-us/library/bb787181(VS.85).aspx

L'avantage de cette approche est qu'aucun logiciel supplémentaire ne doit être installé sur le système affecté. Saisissez-le et déchirez-le, bébé!


la source
1

D'après mon expérience, ce sont surtout des problèmes de corruption de la mémoire.

Par exemple :

char a[8];
memset(&a[0], 0, 16);

: /*use array a doing some thing */

il est très possible d'être normal en mode débogage quand on exécute le code.

Mais en version, ce serait / pourrait être un crash.

Pour moi, fouiller là où la mémoire est hors de propos est trop pénible.

Utilisez certains outils comme Visual Leak Detector (Windows) ou valgrind (Linux) sont plus judicieux.

Gaiger Chen
la source
1

J'ai vu beaucoup de bonnes réponses. Cependant, il n'y en a aucun qui m'a aidé. Dans mon cas, il y a eu une mauvaise utilisation des instructions SSE avec la mémoire non alignée . Jetez un œil à votre bibliothèque mathématique (si vous en utilisez une) et essayez de désactiver le support SIMD, recompilez et reproduisez le plantage.

Exemple:

Un projet inclut mathfu et utilise les classes avec le vecteur STL: std :: vector <mathfu :: vec2> . Une telle utilisation provoquera probablement un plantage au moment de la construction de l' élément mathfu :: vec2 car l'allocateur par défaut de la STL ne garantit pas l'alignement de 16 octets requis. Dans ce cas pour prouver l'idée, on peut définir #define MATHFU_COMPILE_WITHOUT_SIMD_SUPPORT 1avant chaque inclusion du mathfu , recompiler en configuration Release et vérifier à nouveau.

Les configurations Debug et RelWithDebInfo ont bien fonctionné pour mon projet, mais pas pour la version Release . La raison derrière ce comportement est probablement parce que le débogueur traite les demandes d'allocation / désallocation et effectue une certaine comptabilité de mémoire pour vérifier et vérifier les accès à la mémoire.

J'ai vécu la situation dans les environnements Visual Studio 2015 et 2017.

Vlad Serhiienko
la source
0

Quelque chose de similaire m'est arrivé une fois avec GCC. Il s'est avéré être une optimisation trop agressive qui n'a été activée que lors de la création de la version finale et non pendant le processus de développement.

Eh bien, à vrai dire, c'était ma faute, pas celle de gcc, car je n'avais pas remarqué que mon code reposait sur le fait que cette optimisation particulière n'aurait pas été effectuée.

Il m'a fallu beaucoup de temps pour le retracer et je n'y suis venu que parce que j'ai posé la question sur un groupe de discussion et que quelqu'un m'a fait réfléchir. Alors, permettez-moi de vous rendre la pareille au cas où cela vous arriverait également.

Remo.D
la source
0

J'ai trouvé cet article utile pour votre scénario. ISTR les options du compilateur étaient un peu obsolètes. Regardez autour de vos options de projet Visual Studio pour voir comment générer des fichiers pdb pour votre version de version, etc.

pétillant
la source
0

Il est suspect que cela se produise à l'extérieur du débogueur et non à l'intérieur; l'exécution dans le débogueur ne modifie normalement pas le comportement de l'application. Je vérifierais les différences d'environnement entre la console et l'IDE. Aussi, évidemment, compilez la version sans optimisations et avec des informations de débogage, et voyez si cela affecte le comportement. Enfin, consultez les outils de débogage post-mortem que d'autres personnes ont suggérés ici, vous pouvez généralement en obtenir des indices.

pseudo
la source
0

Le débogage des versions de version peut être pénible en raison des optimisations modifiant l'ordre dans lequel les lignes de votre code semblent être exécutées. Cela peut vraiment être déroutant!

Une technique pour au moins réduire le problème consiste à utiliser MessageBox () pour afficher des instructions rapides indiquant à quelle partie du programme votre code est arrivé ("Démarrage de Foo ()", "Démarrage de Foo2 ()"); commencez à les mettre au sommet des fonctions dans la zone de votre code que vous soupçonnez (que faisiez-vous au moment où il s'est écrasé?). Lorsque vous pouvez déterminer quelle fonction, changez les boîtes de message en blocs de code ou même en lignes individuelles dans cette fonction jusqu'à ce que vous la réduisiez à quelques lignes. Ensuite, vous pouvez commencer à imprimer la valeur des variables pour voir dans quel état elles se trouvent au moment de la panne.


la source
Il a déjà essayé de saupoudrer de printfs, donc les boîtes de message ne sont plus; n'apporter rien de nouveau à la fête.
Greg Whitfield
0

Essayez d'utiliser _CrtCheckMemory () pour voir dans quel état se trouve la mémoire allouée. Si tout se passe bien, _CrtCheckMemory renvoie TRUE , sinon FALSE .

Vhaerun
la source
0

Vous pouvez exécuter votre logiciel avec les indicateurs globaux activés (regardez dans les outils de débogage pour Windows). Cela aidera très souvent à résoudre le problème.

Marcin Gil
la source
0

Faites en sorte que votre programme génère un mini-vidage lorsque l'exception se produit, puis ouvrez-le dans un débogueur (par exemple, dans WinDbg). Les principales fonctions à examiner: MiniDumpWriteDump, SetUnhandledExceptionFilter

Mikhailitsky
la source
0

Voici un cas que j'ai eu que quelqu'un pourrait trouver instructif. Il ne s'est écrasé que dans la version de Qt Creator - pas lors du débogage. J'utilisais des fichiers .ini (car je préfère les applications qui peuvent être copiées sur d'autres lecteurs, par rapport à celles qui perdent leurs paramètres si le registre est corrompu). Cela s'applique à toutes les applications qui stockent leurs paramètres dans l'arborescence de répertoires des applications. Si les versions de débogage et de publication se trouvent dans des répertoires différents, vous pouvez également avoir un paramètre différent entre eux. J'avais préférence enregistré dans un qui n'était pas enregistré dans l'autre. Cela s'est avéré être la source de mon accident. Heureusement que je l'ai trouvé.

Je déteste le dire, mais je n'ai diagnostiqué le crash que dans MS Visual Studio Community Edition; après avoir installé VS, laisser mon application se bloquer dans Qt Creator et choisir de l'ouvrir dans le débogueur de Visual Studio . Bien que mon application Qt ne contienne aucune information de symbole, il s'avère que les bibliothèques Qt en avaient. Cela m'a conduit à la ligne offensante; puisque je pouvais voir quelle méthode était appelée. (Pourtant, je pense que Qt est un framework LGPL pratique, puissant et multiplateforme.)

CodeLurker
la source
-3

J'ai eu cette erreur et vs s'est écrasé même en essayant de! Nettoyer! mon projet. J'ai donc supprimé les fichiers obj manuellement du répertoire Release, et après cela, il s'est construit très bien.

Chris89
la source
-6

Je suis d'accord avec Rolf. Parce que la reproductibilité est si importante, vous ne devriez pas avoir de mode sans débogage. Toutes vos versions doivent être déboguables. Avoir deux cibles à déboguer plus que doubler votre charge de débogage. Envoyez simplement la version "mode débogage", sauf si elle est inutilisable. Dans ce cas, rendez-le utilisable.

wnoise
la source
Cela peut fonctionner pour 10% des applications mais certainement pas pour toutes. Souhaitez-vous jouer à des jeux sortis sous la forme de DEBUG? Donnez votre code de sécurité secret de marque en mode facile à démonter, peut-être même avec les PDB? Je suppose que non.
steffenj
Steffenj: Je veux que les développeurs de jeux trouvent des bogues. Idéalement, avant leur expédition, mais si c'est après, je veux qu'ils puissent obtenir suffisamment d'informations pour les reproduire et les retracer. s'il s'agit d'un code secret, la marque ne s'applique pas. PDB? Banque de données sur les protéines? débogueur python?
wnoise
IMHO, c'est une mauvaise idée. Les exécutables sont plus gros, ils ne sont pas optimisés et s'exécutent beaucoup plus lentement. Ces cas sont vraiment assez rares; même si particulièrement exaspérants quand ils se produisent. Vous ne devriez pas fournir un produit toujours de qualité inférieure, en vous inquiétant du débogage extrêmement rare du pire des cas. (Le mien n'était pas l'un des nombreux votes négatifs.) J'ai fait de la programmation pour la NASA; et nous avons dit qu'au strict minimum, chaque ligne de code devrait être testée une fois. Les tests unitaires peuvent également aider.
CodeLurker