62 votes

Existe-t-il une option GCC pour prévenir de l’écriture de `this-field` au lieu de` this-> field`?

Ce code suivant (contenant un bogue vicieux) est compilé avec GCC sans aucun avertissement. Mais, bien sûr, cela ne fonctionne pas comme prévu par le développeur (moi).

 #include <iostream>

struct A
{
    bool b;
    void set(bool b_) { this->b = b_; }
    bool get() const { return this-b; } // The bug is here: '-' instead of '->'
};

int main()
{
    A a;
    a.set(true);
    std::cout << a.get() << std::endl; // Print 1
    a.set(false);
    std::cout << a.get() << std::endl; // Print 1 too...
    return 0;
}
 

Quel avertissement puis-je ajouter pour le compilateur (GCC 4.8) afin d'éviter ce type de faute de frappe?

Question liée: Existe-t-il une option pour forcer (ou avertir) l'accès aux variables / fonctions membres avec this-> ?

71voto

Arne Vogel Points 506

Ce problème particulier est détecté par cppcheck:

$ cppcheck --enable=tous ce-moins-bool.cxx 
La vérification de cette moins-bool.cxx...
[ce-moins-bool.cxx:7]: (avertissement) Suspect pointeur de la soustraction. Avez-vous l'intention d'écrire '->'?
(information) Cppcheck ne peut pas trouver tous les fichiers à inclure (utiliser --check-config pour plus de détails)

C'était sans inclure chemin donné. Si j'ajoute -I /usr/include/c++/4.8/, la question est toujours détecté:

La vérification de cette moins-bool.cxx...
[ce-moins-bool.cxx]: (de l'information) Trop de #ifdef configurations - cppcheck vérifie seulement 12 de 45 configurations. Utilisation de --force pour vérifier toutes les configurations.
[ce-moins-bool.cxx:7]: (avertissement) Suspect pointeur de la soustraction. Avez-vous l'intention d'écrire '->'?
[/usr/include/c++/4.8/bits/ostream.tcc:335]: (de style) Struct '__ptr_garde' a un constructeur avec 1 argument qui n'est pas explicite.
[/usr/include/c++/4.8/bits/locale_classes.tcc:248]: (erreur) Désallocation une désalloué pointeur: __c

et puis cppcheck lentement fonctionne à travers ladite #ifdef configurations.

(Comme une note de côté, l'erreur en local_classes.tcc est un faux positif, mais c'est très difficile à dire un outil automatisé, comme il aurait besoin d'être conscient que l' catch bloc à ce site ne doit pas être saisi au moment de la macro __EXCEPTIONS est vide.)

Avertissement: je n'ai pas d'expérience avec cppcheck.

32voto

Bathsheba Points 23209

Non, this - b est la scène de l'arithmétique des pointeurs sur le pointeur this, malgré b être bool type (b est implicitement converti en int).

(Fait intéressant, vous pouvez toujours ensemble this + b d'un pointeur à l'endroit où b est bool , puisque vous pouvez définir un pointeur vers un passé la fin d'un scalaire! Donc même votre préféré à un comportement indéterminé spotter permettrait à celui-là.)

Les limites du tableau de vérification a toujours été le travail d'un programmeur C++.

Notons également que, dans votre cas, l'utilisation d' this est superflu: afin de mettre un terme à ce recours excessif est une manière de réaliser le problème.

13voto

Simon Points 463

Je voudrais suggérer un autre outil (en dehors de cppcheck proposé par @ arne-vogel), donnant une meilleure aide visuelle au lieu de l'avertissement demandé:

Utilisez le format Clang pour formater automatiquement votre code. Le résultat pourrait ressembler à ceci (selon les paramètres), rendant le bogue plus visible par les espaces ajoutés autour de operator- :

 struct A {
  bool b;
  void set(bool b_) { this->b = b_; }
  bool get() const { return this - b; }
};
 

-1voto

Richard Hodges Points 1972

Non, il n'y a aucun moyen d'obtenir un avertissement. Les conversions implicites, bien que pervers, sont autorisés par la langue.

Toutefois, dans ce cas d'utilisation spécifiques que nous pouvons faire mieux en enveloppant l'bool dans une classe wrapper qui a des conversions explicites et pas d'opérations arithmétiques définis.

Cela génère une erreur de compilation lors de l'logiquement mal utilisé, ce qui est normalement considéré comme préférable à un avertissement si la logique de l'exactitude est l'objectif.

Il est intéressant de noter que le c++17 dénonçait bool::operator++ que cette arithmétique est vu comme un mal.

exemple:

struct Bool
{
    explicit Bool(bool b) : value_(b) {}
    explicit operator bool() const { return value_; }
private:
    bool value_;

    // define only the operators you actually want
    friend std::ostream& operator<<(std::ostream& os, const Bool& b) {
        return os << b;
    }
};

struct X
{
    bool foo() {
        // compilation failure - no arithemetic operators defined.
        // return bool(this-b);

        // explicit conversion is fine
        return bool(b);
    }

    Bool b { true }; // explicit initialisation fine
};

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X