56 votes

Résultats différents entre gcc et clang lors de la compilation d'un programme c++11 assez simple

J'essaie de comprendre si le comportement différent exposé par gcc et clang dans la sortie de ce simple programme C++11 est dû à un bogue dans clang (Xcode 5.0.2, OS X 10.8.5). Le code est le suivant :

#include <iostream>

int main() {

    int matrix[][3]{{1,2,3}, {4,5,6}, {7,8,9}};
    auto dyn_matrix = new int[3][3]{{1,2,3}, {4,5,6}, {7,8,9}};

    std::cout << matrix[0][1] << std::endl;
    std::cout << dyn_matrix[0][1] << std::endl;

    return 0;   
}

Comme indiqué, j'essaie d'utiliser l'initialisation uniforme pour initialiser un tableau multidimensionnel anonyme (resp. nommé) de taille 3x3 . En compilant avec gcc 4.7 de MacPorts, la sortie attendue est obtenue :

$g++-mp-4.7 -std=c++11 dyn_matrix.cpp -o dyn_matrix 
$ ./dyn_matrix
2
2
$

Inversement, dans le cas où clang est utilisé, la sortie se lit comme suit :

$ clang++ -std=c++11 -stdlib=libc++ dyn_matrix.cpp -o dyn_matrix_clang
$ ./dyn_matrix_clang 
2
4
$  

Dans ce cas, le résultat est (apparemment) erroné. clang --version rapports :

Apple LLVM version 5.0 (clang-500.2.75) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix

Qui est à blâmer ? Moi, gcc ou clang ?

MISE À JOUR du 11 décembre 2013 : Le bogue aurait dû être corrigé dans la r196995. Malheureusement, nous ne savons toujours pas combien de temps il faudra avant qu'Apple mette à jour la version de clang fournie avec Xcode.

MISE À JOUR du 9 décembre 2013 : J'ai soumis un rapport de bogue sur la plateforme bugzilla de LLVM. Il a effectivement été reconnu comme un bug, un patch est actuellement en cours d'examen, voir http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20131209/095099.html .

Gracias.

20voto

Matthieu M. Points 101624

Mise à jour : Grâce à Faisal Vali et Richard Smith, ce bogue a été corrigé dans la ToT de Clang ; voir le fichier fichier test introduite par l'engagement.


Selon §8.5.1 [dcl.init.aggr] il semble que Clang ait tort :

11/ Les accolades peuvent être élidées dans une liste d'initialisation comme suit. Si le liste d'initialisation commence par une accolade gauche, puis la liste suivante, séparée par des virgules, des éléments suivants Clauses d'initialisation initialise les membres d'un sous-agrégat ; il est erroné d'avoir plus de Clauses d'initialisation que les membres. Si, toutefois, le liste d'initialisation pour un sous-agrégat ne commence pas par une accolade gauche, alors il suffit d'une quantité suffisante de Clauses d'initialisation de la liste sont pris pour initialiser les membres du sous-agrégat ; tout élément restant Clauses d'initialisation sont laissés pour initialiser le prochain membre de l'agrégat dont le sous-agrégat actuel est membre. [ Exemple :

float y[4][3] = {
    { 1, 3, 5 },
    { 2, 4, 6 },
    { 3, 5, 7 },
};

est une initialisation complète : 1, 3, et 5 initialisent la première ligne du tableau y[0] à savoir y[0][0] , y[0][1] y y[0][2] . De même, les deux lignes suivantes initialisent y[1] y y[2] . L'initialisateur se termine tôt et donc y[3] sont initialisés comme s'ils étaient explicitement initialisés avec une expression de la forme float() c'est-à-dire qu'ils sont initialisés avec 0.0 . Dans l'exemple suivant, les accolades dans le champ liste d'initialisation sont élidés ; toutefois, le liste d'initialisation a le même effet que l'armature complète. liste d'initialisation de l'exemple ci-dessus,

float y[4][3] = {
    1, 3, 5, 2, 4, 6, 3, 5, 7
};

L'initialisateur de y commence par une accolade gauche, mais celui de y[0] ne le fait pas, donc trois éléments de la liste sont utilisés. De même les trois suivants sont pris successivement pour y[1] y y[2] . - exemple de fin ]

Ce qui, je pense, s'applique à cause de §5.3.4 [expr.new] :

15/ A nouvelle-expression qui crée un objet de type T initialise cet objet comme suit :

  • Si le new-initializer est omis, l'objet est initialisé par défaut ( §8.5 ) ; si aucune initialisation n'est effectuée, l'objet a une valeur indéterminée.
  • Dans le cas contraire, le new-initializer est interprété selon les règles d'initialisation de §8.5 pour une initialisation directe.

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