Question

est Assertion utilisé pour vérifier si une condition est remplie (condition sine qua non, postcondition, invariants) et aider les programmeurs à trouver des trous pendant la phase de débogage.

Par exemple,

void f(int *p)
{
  assert(p);
  p->do();
}

Ma question est de savoir si nous devons assumer la condition ne pouvait être satisfaite en mode de libération et de gérer le cas en conséquence?

void f(int *p)
{
  assert(p);

  if (p)
  {
    p->do();
  }
}

Après tout, un moyen d'affirmation que la condition qu'elle teste ne doit jamais être faux. Mais si, si nous ne contrôlons pas et il tombe en panne, plante programme. Sonne comme un dilemme. Comment les gars ne vous y faire face?

Était-ce utile?

La solution

Si l'assertion échoue, le programme devrait planter .

Une assertion ne le programmeur moyen a fait une erreur fondamentale dans leur compréhension de la façon dont il est possible pour le déroulement du programme à suivre. Ceci est une aide au développement, et non une aide à la production. Dans la production, on peut gérer exceptions , comme ils "pourraient" se produire, alors que les affirmations doivent "jamais" l'échec.

Si vous êtes dans le camp qui dit: « Oh, mais si les affirmations échouent dans la production? Je besoin de les attraper! » alors vous êtes absent le point. Demandez-vous, dans ce cas, pourquoi ne vous venez de lancer une exception (ou toute autre manipulation de l'erreur)?

D'une manière générale, assert est pas juste un raccourci pour "si la condition non remplie, exception throw" (bien, parfois qui est la sémantique opérationnelle, mais pas la dénotation sémantique). Au contraire, une affirmation des moyens à défaut l'application est un état le développeur ne croit pas est encore possible . Voulez-vous vraiment le code de poursuivre l'exécution dans un tel cas? Il est clair que (je dirais), Non .

Autres conseils

Programmation défensive est toujours préférable. Vous devriez toujours supposer que, malgré tous vos tests, votre application sera livrée avec des bugs. En tant que tel, il est dans votre intérêt d'ajouter des contrôles NULL dans des situations où vous pouvez éviter une déférence de pointeur NULL et simplement passer.

Cependant, il y a des situations où il n'y a tout simplement aucun moyen facile d'éviter un accident, et dans ces cas, l'assertion est votre seule façon de détecter le problème au cours de votre cycle de développement.

Un point important si - affirme sont aussi souvent utilisés pour détecter des problèmes majeurs avec l'intégrité de vos données. Si vous continuez passé les AFFIRME, vous pourriez risquer de corrompre les données. Dans ces cas, il peut être préférable de planter plutôt que de détruire vos données. (De toute évidence, toute sorte de gestionnaire accident au moins une interface utilisateur apporte raisonnable avec une description d'erreur serait préférable).

Strictement parlant, le second code a une redondance.

void f(int *p)
{
  assert(p);
  if (p)    // Beats the purpose of assertion
  {
    p->do();
  }
}

Affirmation erreur de moyens est produite. Quelque chose qui est inattendu / Unhandled. Dans le code ci-dessus, soit

1) Vous gérez correctement le cas où p est nul. (En ne demandant pas P-> faire ()) - qui est censé être le droit / chose prévu de le faire. Cependant, l'affirmation est un fausse alarme .

2) D'autre part, si en ne demandant pas P-> faire (), quelque chose va mal tourner (peut-être plus loin dans le code ou dans la sortie), l'affirmation est juste, mais il devrait y avoir aucun point dans continue de toute façon.

Dans le code ci-dessus le programmeur travaille d'arrache-pied à des cas de poignée qui sont de toute façon erronée.

Cela dit, certaines personnes aiment traiter affirme comme quelque chose a mal, mais permet de voir si nous obtenons encore une sortie correcte . OMI, qui est mauvaise stratégie et crée lors de la fixation des confusions bug.

Assertions sont le code de débogage, pas de code d'exploitation. Ne pas les utiliser pour des erreurs d'entrée de capture.

Assertions sont utilisés à des bogues de capture dans les tests. La théorie est que vous avez testé assez bien pour savoir que cela fonctionnera une fois que vous avez relâcha.

S'il y a une possibilité que la condition pourrait survenir dans le fonctionnement réel de la vie, ne reposent pas sur des affirmations -. Exceptions d'utilisation ou d'un autre mécanisme d'erreur

Affirme sont utiles pour le débogage que vous avez mentionné. Ils ne doivent jamais faire dans le code de production (tel que compilé, il est autorisé à les envelopper dans #ifdefs bien sûr)

Si vous utilisez dans un problème où il est hors de votre contrôle pour corriger et vous devez le vérifier dans votre code de production que je ferais quelque chose comme:

void f(int *p)
{

  if (!p)
  {
    do_error("FATAL, P is null.");
  }

  p->do();
}

Où do_error est une fonction qui enregistre une erreur et sort proprement.

Je dis les laisser dans un communiqué de construction. Il y a forcément des bugs dans toute construction. Avoir dans vos moyens affirme de ce produit, vous pouvez identifier le problème plus facilement lorsque vous recevez un rapport de problème à Uwer.

Ne pas mettre beaucoup d'efforts dans le traitement des exceptions. Assurez-vous simplement que vous pouvez saisir l'exception complète, includigg stacktrace. Cela vaut pour à la libération de construction en particulier.

Étant donné que beaucoup de gens commentent la mise en mode assertions de sortie:

Dans ce que je travaille sur, l'efficacité est très important (parfois, l'exécution sur de grands ensembles de données prend des dizaines d'heures à quelques jours pour terminer). Par conséquent, nous avons des macros spéciales qui affirment que dans le code de débogage (exécuter pendant QA, etc.). À titre d'exemple, une assertion dans une boucle est sans aucun doute une surcharge et vous pouvez l'éviter dans le code de déverrouillage. Après tout, si tout bien iz, affirme ne sont pas censés à l'échec.

Un exemple où le code de libération affirme sont bons est - si la logique n'est pas censé frapper une branche de code particulier du tout. Dans ce cas, assert (0) est très bien [ainsi toute sorte de assert (0) peut toujours être laissé dans le code de libération].

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top