12
votes

Détecter la dimension élue accidentelle en C ++

Considérez l'extrait suivant:

#include <iostream>
using namespace std;

int a[10][2];
int b[10][2];

int main(){

  //intended
  cout << a[0][0] - b[0][0] << endl;

  //left out dimension by mistake
  cout << a[0] - b[0] << endl;

}


9 commentaires

Si je ne me trompe pas, seuls l'arithmétique entre les pointeurs correspondants est un comportement défini. Les "pointeurs" a [0] et b [0] ne sont pas vraiment liés, c'est donc le comportement le plus indéfini IMO.


Vous pouvez régler votre compilateur pour imprimer l'arborescence d'analyse et vérifier si des expressions arithmétiques impliquent des opérandes de type pointeur. Clang pourrait rendre cela facile, aucune idée.


Ah, à la lumière de Joachims Observation astucieuse, essayez l'Ubsan de Clang.


@Kerreksb Eh bien, je pourrais avoir tort (on sait qu'il se passe!). Je me souviens juste de la lire quelque part "officiel". :)


Intéressant Comme je n'ai essayé que GCC jusqu'à présent avec l'énorme ensemble d'indicateurs d'avertissement énumérés dans Stackoverflow.com/questions/399850/... Je vais donner un coup de collage. Nous n'utilisons normalement pas cela ici.


@ Joachimpileborg: Vous avez raison. La clause pertinente est de 5,7 [EXPR.ADD] paragraphe 6.


@Frankc: Vous pouvez utiliser Clang pour l'analyse statique et les messages d'erreur utiles, ainsi que GCC pour le code bien généré :-)


Aléatoire cependant: Utilisez des expressions régulières pour correspondre à tout [numéro] Opération [numéro] ?


J'ai essayé Clang ++ avec -fsanitize = non défini, ainsi que -wall -Pachetic et il n'y avait pas d'avertissements sur ce code de test. C'est une version plus ancienne de Clang cependant dans mon repo (2.8) afin que je puisse avoir besoin d'essayer un plus récent


3 Réponses :


2
votes

Si cela ne concerne que << Opérateur comme par exemple, la surcharge de l'opérateur << pour INT * pourrait aider - vous pouvez surcharger l'opérateur pour générer une erreur de compilation.


1 commentaires

Malheureusement, c'était juste un moyen pour moi de montrer cet exemple dans un petit extrait. En réalité, il est beaucoup plus insidieux, jonchée le long d'un tas de déclarations dans un énorme morceau de code scientifique. Bonne pensée, cependant.



8
votes

Vous pouvez utiliser std :: Array code> qui ne permettra pas de:

    using d1=std::array<int, 2>;
    using d2=std::array<d1, 10>;

    d2 a;
    d2 b;

    std::cout << a[0][0] - b[0][0] << endl;  // works as expected

    std::cout << a[0] - b[0] << endl;        // will not compile


1 commentaires

J'ai essayé cela et ça échoue à compiler comme prévu. Je préférerais réellement quelque chose qui a des avertissements sur le code inchangé existant, mais je n'ai donc rien essayé de le faire, c'est la meilleure réponse



4
votes

Une autre option consiste à utiliser une bibliothèque de réseau multidimensionnelle spécialisée avec la manipulation des erreurs d'opérateur appropriées, telles que Boost :: Multi_array ( http://www.boost.org/doc/libs/1_55_0/libs/Multi_array/doc/user.html ). C'est généralement une meilleure idée que d'utiliser des récipients imbriqués ou des tableaux de pod.


0 commentaires