web-dev-qa-db-fra.com

Trouver facilement les variables de membre non initialisées

Je cherche un moyen facile de trouver des variables de membre de classe non initialisées.

Les trouver dans runtime ou compile time est OK.

Actuellement, j'ai un point d'arrêt dans le constructeur de la classe et j'examine les variables de membre une par une.

44
user254669

Si vous utilisez GCC, vous pouvez utiliser l'indicateur -Weffc++, qui génère des avertissements lorsqu'une variable n'est pas initialisée dans la liste d'initialisation des membres. Ce:

class Foo
{
  int v;
  Foo() {}
};

Mène à:

$ g++ -c -Weffc++ foo.cpp -o foo.o
foo.cpp: In constructor ‘Foo::Foo()’:
foo.cpp:4: warning: ‘Foo::v’ should be initialized in the member initialization list

Un inconvénient est que -Weffc++ vous avertira également lorsqu'une variable a un constructeur par défaut approprié et que l'initialisation ne serait donc pas nécessaire. Il vous avertira également lorsque vous initialisez une variable dans le constructeur, mais pas dans la liste d'initialisation des membres. Et il met en garde sur de nombreux autres problèmes liés au style C++, tels que les constructeurs de copie manquants. Vous devrez peut-être nettoyer un peu votre code lorsque vous souhaitez utiliser -Weffc++ de manière régulière.

Il y a aussi un bogue qui vous donne toujours un avertissement lors de l'utilisation d'unions anonymes, que vous ne pouvez actuellement pas contourner autrement que de désactiver l'avertissement, ce qui peut être fait avec:

#pragma GCC diagnostic ignored "-Weffc++"

Cependant, dans l’ensemble, j’ai trouvé que -Weffc++ était incroyablement utile pour attraper de nombreuses erreurs C++ courantes.

28
Grumbel

Valgrind peut vous dire si vous êtes sur Linux.

10
Zitrax

Valgrind (FREE, sous Linux) et Purify (sous Windows) trouve des variables non initialisées, des pointeurs invalides, etc. en exécutant votre code dans une machine virtuelle spéciale.

Ceci est facile à utiliser et extrêmement puissant; il y aura probablement de nombreux bogues au-delà des variables non initialisées évidentes.

Coverity , Klocwork et Lint peut trouver des variables non initialisées à l'aide d'une analyse de code statique.

10
Will

cppcheck trouvera ceci, par exemple:

cppcheck my_src_dir --output-file=check.txt --inconclusive --enable=warning
8
Johan Kotlinski

-Wuninitialized

(Ceci vérifie seulement si une variable est utilisée non initialisée, c’est-à-dire si

struct Q { 
  int x, y;
  Q() : x(2) {}
  int get_xy() const { return x*y; }
};

g ++ avertira uniquement lorsque l'utilisateur appelle get_xy() sans affecter à y.)

6
kennytm

Visual Studio (MSVC) possède une option de compilateur/sdl (Enable Additional Security Checks) ( http://msdn.Microsoft.com/en-us/library/jj161081.aspx ). Au moment de l'exécution, il:

Effectue l'initialisation du membre de la classe. Initialise automatiquement la classe membres de type pointeur mis à zéro lors de l'instanciation de l'objet (avant l'exécution du constructeur ). Cela permet d’empêcher l’utilisation de données non initialisées associé à des membres de classe que le constructeur ne fait pas explicitement initialiser.

Cela ne vous aidera pas à détecter les variables membres non initialisées au moment de la compilation, mais rend le comportement plus prévisible lorsqu'il se produit au moment de l'exécution. Vous ne devriez pas écrire de code qui repose sur l'activation de cette option, bien sûr.

5
Quatari

Si vous utilisez Visual Studio, vous pouvez compiler en mode débogage, arrêter le programme dans le débogueur et rechercher les variables initialisées sur les octets contenant 0xCC (pile) ou 0xCD (tas).

Personnellement, j'investirais dans un outil d'analyse statique pour une approche plus approfondie.

4
Kaz Dragon
2
Terry Mahaffey

Clang avec clang-analyse est capable de le faire. Il créera éventuellement un rapport Nice HTML indiquant à quel moment la variable inutilisée est utilisée. 

0

Il faut se méfier! Les options du compilateur proposées ici ne sont ni fiables, ni indépendantes de la version. Prenons l'exemple simple:

class A {
  int a;
public:
  void mA() {
    printf("haha");
    ++a;
    int g = 2/a;
    printf("%i\n",g);
  }
};

int main() {
  A a;
  a.mA();
}

Compilé avec g++ -O3 -Weffc++ -Wuninitialized, cette chose affiche uninitialized sur les versions de gcc jusqu’à la version 4.6 incluse, et passe heureusement sur les versions 4.7 et 4.8 (testé sur MacPorts). Ensuite, curieusement, si nous retirons la printf("haha");, 4.7 et 4.8 voient tout à coup uninitialized A::a. Clang est un peu mieux, car il attribue en quelque sorte des ordures (au lieu de 0) aux vars non initialisés, vous voyez ainsi leur effet désastreux plus facilement/plus tôt. 

Je n'ai pas eu beaucoup de chance en repérant le A::a non initialisé ci-dessus avec valgrind non plus; peut-être que la suggestion suggérant valgrind pourrait fournir des options appropriées pour détecter cette erreur. 

En bout de ligne: excellente question, peu de solutions fiables pour le moment ... (à mon sens).

0
P Marecki