Question

Je veux dire par là, que dois-je faire pour avoir des assertions utiles dans mon code?

MFC est assez simple, je viens d'utiliser ASSERT (quelque chose).

Quelle est la méthode non-MFC?

Modifier: Est-il possible d'arrêter l'assertion de l'assertion dans assert.c plutôt que dans mon fichier appelé assert ()?

Modifier: quelle est la différence entre <assert.h> & amp; <cassert>?

Réponse acceptée: Cet excellent article contient de nombreuses bonnes réponses. J'aimerais pouvoir accepter plus d'une réponse (sinon quelqu'un pourrait les combiner toutes). Donc, la réponse est attribuée à Ferruccio (pour la première réponse).

Était-ce utile?

La solution

#include <cassert>

assert(something);

et pour la vérification à la compilation, les assertions statiques de Boost sont très utiles:

#include <boost/static_assert.hpp>

BOOST_STATIC_ASSERT(sizeof(int) == 4);  // compile fails if ints aren't 32-bit

Autres conseils

Cela dépend si vous recherchez ou non quelque chose qui fonctionne en dehors de Visual C ++. Cela dépend également du type d’affirmation que vous recherchez.

Il existe quelques types d’affirmations:

  1. Préprocesseur
    Ces assertions sont effectuées à l'aide de la directive préprocesseur #error
    Les assertions de pré-traitement ne sont évaluées que pendant la phase de pré-traitement et ne sont donc pas utiles pour des éléments tels que les modèles.

  2. Heure d'exécution
    Ces assertions sont effectuées à l'aide de la fonction assert() définie dans <cassert>
    Les assertions d'exécution ne sont évaluées qu'au moment de l'exécution. Et comme l'a souligné BoltBait, ils ne sont pas compilés si la NDEBUG macro a été définie.

  3. Static
    Comme vous l'avez dit, ces assertions sont effectuées à l'aide de la macro ASSERT(), mais uniquement si vous utilisez MFC. Je ne connais pas d'autre moyen de faire des assertions statiques faisant partie de la norme C / C ++. Toutefois, la bibliothèque Boost offre une autre solution: static_assert.
    La fonction <=> de la bibliothèque Boost est quelque chose qui va être ajouté dans le C ++. 0x standard .

En guise d’avertissement supplémentaire, la fonction <=> proposée par Ferruccio ne présente pas le même comportement que la macro MFC <=>. La première est une assertion d'exécution, tandis que la dernière est une assertion statique.

J'espère que cela aide!

Assert est (généralement) un débogage uniquement

Le problème avec " assert " c’est qu’il s’agit généralement de binaires de débogage et que certains développeurs les utilisent comme si le code était toujours en production.

Ce n’est pas un mal en soi, car le code est censé être testé de manière intensive et, par conséquent, les bogues générant l’affirmation seront sûrement découverts et supprimés.

Mais parfois (la plupart du temps?), les tests ne sont pas aussi intensifs que souhaité. Je ne parlerai pas d'un vieil emploi où nous devions coder jusqu'à la toute dernière minute ( ne demande pas ... Parfois, les gestionnaires sont juste ... Ahem ... ) ... Quel est l'intérêt d'une affirmation que vous ajoutez à un code qui sera compilé et livré au client sous forme de binaire d'édition au prochain moment?

Assert dans (certaines) applications réelles

Dans notre équipe, nous avions besoin de quelque chose pour détecter l'erreur, mais aussi d'un autre moyen pour la gérer. Et nous en avions besoin, potentiellement, dans Release Build.

Assert détectera et gérera l'erreur uniquement lors de la construction du débogage.

Nous avons donc ajouté une macro XXX_ASSERT ainsi qu'une macro XXX_RAISE_ERROR.

La macro XXX_ASSERT ferait la même chose que la macro ASSERT, mais elle serait construite à la fois dans Debug et dans Release. Son comportement (écrire un journal, ouvrir une boîte de message, ne rien faire, etc.) pourrait être contrôlé par un fichier .INI, et ALORS, il abandonnerait / quitterait l'application.

Ceci a été utilisé comme:

bool doSomething(MyObject * p)
{
   // If p is NULL, then the app will abort/exit
   XXX_ASSERT((p != NULL), "Hey ! p is NULL !") ;

   // etc.
}
La macro

XXX_RAISE_ERROR ne contiendrait que & "log &"; l'erreur, mais ne tenterait pas de la gérer. Cela signifie qu'il peut consigner le message dans un fichier et / ou ouvrir une boîte de message avec le message, un bouton pour continuer et un autre pour lancer une session de débogage (selon la configuration du fichier .INI). Ceci a été utilisé comme:

bool doSomething(MyObject * p)
{
   if(p == NULL)
   {
      // First, XXX_RAISE_ERROR will alert the user as configured in the INI file
      // perhaps even offering to open a debug session
      XXX_RAISE_ERROR("Hey ! p is NULL !") ;
      // here, you can handle the error as you wish
      // Than means allocating p, or throwing an exception, or
      // returning false, etc.
      // Whereas the XXX_ASSERT could simply crash.
   }

   // etc.
}

Un an après leur introduction dans nos bibliothèques, seul XXX_RAISE_ERROR est utilisé. Bien sûr, il ne peut pas être utilisé sur des parties critiques de l'application (nous avons un XXX_RAISE_ERROR_DBG pour cela), mais partout ailleurs, c'est bon. Et le fait que l’on puisse utiliser ce que l’on préfère en matière de traitement des erreurs et que celui-ci peut être activé à volonté, soit sur l’ordinateur du développeur, soit sur le testeur, voire même sur l’utilisateur, est très utile.

Pour répondre à la question dans votre deuxième " modifier " ;:

< assert.h > est l'en-tête C

< cassert > est l'en-tête de la bibliothèque standard C ++ ... il comprend généralement < assert.h >

Pour entrer dans le fichier qui a appelé l'assertion, vous pouvez utiliser une macro personnalisée qui lève une exception ou appelle __debugbreak:

#define MYASSERT(EXPR, MSG) if (!(EXPR)) throw MSG;

Ou:

#define MYASSERT(EXPR) if (!(EXPR)) __debugbreak();

Utilisation d'assertion de base

#include <cassert>

/* Some code later */
assert( true );

Notes sur les meilleures pratiques

Les assertions sont utilisées pour identifier les états d’exécution qui devraient être vrais . En conséquence, ils sont compilés en mode release.

Si vous souhaitez qu'une assertion frappe toujours, vous pouvez lui donner une valeur fausse. Par exemple:

switch ( someVal ):
{
case 0:
case 1:
  break;
default:
  assert( false ); /* should never happen */
}

Il est également possible de transmettre un message via assert:

assert( !"This assert will always hit." );

Les bases de code matures étendent fréquemment la fonctionnalité assert. Certaines des extensions communes incluent:

  • Basculement des assertions module par module pour localiser les tests.
  • Création d'une macro d'assertion supplémentaire compilée dans la plupart des versions de débogage. Cela est souhaitable pour le code appelé très fréquemment (des millions de fois par seconde) et qui ne sera probablement pas incorrect.
  • Permettre aux utilisateurs de désactiver l'assertion de hit en cours, toutes les assertions de l'unité de compilation ou toutes les assertions de la base de code. Cela empêche le déclenchement d'assertions bénignes et crée des versions inutilisables.

Le CRT spécifique à Microsoft affirme

#include <crtdbg.h>
#include <sstream>
...
// displays nondescript message box when x <= 42
_ASSERT(x > 42);
// displays message box with "x > 42" message when x <= 42
_ASSERTE(x > 42);
// displays message box with computed message "x is ...!" when x <= 42
_ASSERT_EXPR(
   x > 42, (std::stringstream() << L"x is " << x << L"!").str().c_str());

Il existe une bibliothèque open source plus avancée appelée ModAssert, qui contient des assertions qui fonctionnent à la fois avec Visual C ++ et gcc. Probablement aussi sur d'autres compilateurs, je ne le sais pas avec certitude. Il faut un certain temps pour l’apprendre, mais si vous voulez de bonnes assertions qui ne dépendent pas de MFC, regardez-les. C'est à http://sourceforge.net/projects/modassert/

utilisez intellisense pour l’ouvrir dans Visual Studio (clic droit)

// cassert standard header
#include <yvals.h>
#include <assert.h>

yvals.h est un logiciel Windows. ainsi, en ce qui concerne assert (), les deux manières de l'inclure sont identiques. C'est une bonne pratique d'utiliser <cxxx> car souvent ce n'est pas si simple (habillage de l'espace de noms et peut-être une autre magie)

Cela s’arrête sur le site de l’appelant pour moi ...

voici un article expliquant pourquoi vous ne voulez pas écrire cette macro vous-même.

Voici l'itération la plus récente d'une installation d'assertion en C ++: http://pempek.net/articles/2013/11/17/cross-platform-cpp-assertion-library/

C'est une librairie à insérer de 2 fichiers que vous pouvez facilement ajouter à votre projet.

Pour répondre à la troisième question du demandeur: la première raison pour laquelle nous utilisons " cassert " au lieu de " assert.h " C’est parce que, dans le cas de C ++, on tient compte du fait que le compilateur C ++ peut ne pas stocker les descriptions de fonctions dans des fichiers de code, mais dans une dll ou dans le compilateur lui-même. La seconde est que des modifications mineures peuvent être apportées aux fonctions afin de faciliter les différences entre C et C ++, présentes ou à venir. Assert.h étant une bibliothèque C, il est préférable d’utiliser & «Cassert &»; en C ++.

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