Licence CC 0

Découverte d'un bug avec MSVC

Pour une fois, je peux me plaindre du compilateur !

Publié :
Auteur :
Catégorie :
Temps de lecture estimé : 1 minute

Aujourd’hui, j’ai découvert un bug dans MSVC, le compilateur de Microsoft fourni par Visual Studio. Et tout a commencé par un commentaire de @BIOoOAG sur le tutoriel C++. Pendant qu’il lisait le chapitre sur les lambdas, il nous a écrit un message signalant que le code suivant produisait chez lui deux warnings.

#include <iostream>

int main()
{
    bool const a_boolean { true };
    int const an_integer { 42 };
    double const a_real { 3.1415 };

    auto lambda = [a_boolean, an_integer, a_real]() -> void
    {
        std::cout << "Boolean is " << std::boolalpha << a_boolean << "." << std::endl;
        std::cout << "Integer is " << an_integer << "." << std::endl;
        std::cout << "Real is " << a_real << "." << std::endl;
    };

    lambda();
    return 0;
}

Avec MinGW, il avait les deux warnings suivants.

warning: lambda capture 'a_boolean' is not required to be capture for this use. [-Wunused-lambda-capture]
warning: lambda capture 'an_integer' is not required to be capture for this use. [-Wunused-lambda-capture]

Bizarre, avec Visual Studio je n’ai jamais eu ce problème. Comme mes recherches ne donnent rien, je me décide à demander sur SO. La réponse tombe : MinGW et GCC ont raison, MSVC ne respecte pas la norme. En effet, le code suivant, valide, ne compile pas avec le compilateur de Microsoft.

#include <iostream>

int main()
{
    bool const a_boolean { true };
    int const an_integer { 42 };
    double const a_real { 3.1415 };

    // Notez que a_boolean et an_integer ne sont plus explicitement capturés.
    auto lambda = [a_real]() -> void
    {
        std::cout << "Boolean is " << std::boolalpha << a_boolean << "." << std::endl;
        std::cout << "Integer is " << an_integer << "." << std::endl;
        std::cout << "Real is " << a_real << "." << std::endl;
    };

    lambda();
    return 0;
}

La deuxième réponse à cette question dévoile les passages de la norme, soit dit en passant assez compliqués à comprendre, qui expliquent la raison.

Pour la première fois de ma vie, j’ai pu blâmer le compilateur si mon code ne compilait pas. :)



11 commentaires

Cela me fait penser aux chercheurs qui ont trouvé plusieurs centaines de bugs dans GCC avec un générateur automatique de code. Je ne saurai malheureusement pas retrouver l’article.

+2 -0

Ça me fait penser à un bug du compilateur GCC sur lequel j’étais tombé en apprenant Ada (avec le compilateur GNAT qui ce base sur GCC). Un bug rapporté depuis plusieurs années mais qui n’est pas corrigé.

Édité par Heziode

+0 -0

Oui, c’est pas que je critique le warning, c’est surtout que je ne peux pas corriger en ne capturant pas ces variables, sinon ca compile plus sous windows.

Pour poser des questions ou simplement discuter informatique, vous pouvez rejoindre le discord NaN.

+0 -0

Il s’agit de l’article Finding and Understanding Bugs in C Compilers par Xuejun Yang, Yang Chen, Eric Eide, and John Regehr, 2011. Ils ont trouvé des centaines de bugs dans les compilateurs qu’ils ont testé, y compris GCC et Clang/LLVM — sauf dans le compilateur Compcert ou seulement 2 bugs ont été trouvé, si je me souviens bien. Ils ne parlent pas de MSVC parce qu’ils se sont concentrés sur des compilateurs open source.

MSVC a longtemps été un compilateur de merde parce que Microsoft n’avait aucun intérêt à l’améliorer, et préférait la stratégie consistant à forcer les gens à écrire du code Windows-only pour éviter les problèmes de compatibilité, et/ou préférant se concentrer sur des outils C++. Les standards étaient très mal gérés et les problèmes de compatibilité avec les autres compilateurs très très nombreux. Leur support C99 était inexistant (y compris le fait de déclarer des variables au milieu des blocs… je crois que ça a été rajouté en 2013 ?). Depuis ils ont essayé de faire un effort pour éviter d’avoir la honte, embauché des gens qui s’intéressent à C et à C++, ça a un peu progressé.

+1 -0

Ahah, toujours frustrant quand on trouve un bug dans le compilateur. Ca ne m’est jamais arrivé avec MinGW, mais ça m’est arrivé une fois avec javac en Java 9.

Par contre quelqu’un peut m’expliquer pourquoi il n’y a pas besoin de capturer explicitement le bool et le int, mais le double si ?

Est-ce lié au fait qu’on utilise la lambda uniquement dans son contexte emglobant sans en sortir, i.e. pas de closure ? Ou est-ce juste une histoire de copies inutiles, ou parce que les variables sont reconnues de fait comme des constantes ?

C’est plus simple de laisser le compilateur décider tout seul quoi capturer avec [&] ou [=]

Ma plateforme avec 23 jeux de société classiques en 6 langues et 13000 joueurs: http://qcsalon.net/ | Apprenez à faire des sites web accessibles http://www.openweb.eu.org/

+0 -0

Les explications sont sur SO, mais si j’ai bien compris, int const et bool const sont évalués comme des expressions constantes, du coup utilisables dans des contextes où une expression constante est attendue. Exemple : tableau C.

int const a = 5;
int tableau[a];

Alors que double const non. Par contre, si tu remplaces const par constexpr, ça marche pour les trois variables.

Quant à savoir pourquoi y’a capture implicite d’expressions constantes, il faut regarder la norme.

Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte