• [^] # Re: C'est moi ou c'est idiot ?

    Posté par (site web personnel) . En réponse au journal Google forke C++. Évalué à 6.

    Si je peux changer ma représentation interne d'une classe, ne pas recompiler ceux qui utilisent cette classe et tout de même linker avec c'est qu'il n'y a pas de problème d'abi ?

    Ça ne suffit même pas :) Regardez par exemple cette belle lib que l'on va générer en deux versions :

    // lib.hpp
    #pragma once
    struct something
    {
     void print() const;
     int a;
    };
    // lib.cpp
    #include <lib.hpp>
    #include <cstdio>
    void something::print() const
    {
     printf("v1 %d, sizeof(*this)=%lu\n", a, sizeof(*this));
    }

    On compile cela et on envoie le .so au client :

    $ g++ -shared -fPIC -I. lib.cpp -o liblib.so

    De son côté le client écrit ce programme :

    // client.cpp
    #include <lib.hpp>
    #include <cstdio>
    int main()
    {
     int a = 32;
     something s{64};
     int b = 128;
     s.print();
     printf("sizeof(s)=%lu\n", sizeof(s));
     return 0;
    }

    Il compile ça et teste :

    $ g++ -I. client.cpp -o client -Wl,-rpath,'$$ORIGIN' -L. -llib
    $ ./client
    v1 64, sizeof(*this)=4
    sizeof(s)=4

    Tout va pour le mieux.

    Le vendeur de lib fournit maintenant une nouvelle version de sa lib, la version 2, avec deux fois plus de champs dans something.

    // lib.hpp
    #pragma once
    struct something
    {
     void print() const;
     int a;
     int b;
    };
    // lib.cpp
    #include <lib.hpp>
    #include <cstdio>
    void something::print() const
    {
     printf("v2 %d, %d, sizeof(*this)=%lu\n", a, b, sizeof(*this));
    }

    Compilé de la même façon, il envoie le .so au client qui remplace directement l'ancien fichier et relance son programme :

    $ ./client
    v2 64, 32, sizeof(*this)=8
    sizeof(s)=4

    Et voilà, le programme se lance bien, il affiche n'importe quoi (la lib voit dans something::b la valeur 32 qui est dans la pile côté client) et on voit que le client et la lib ne sont pas d'accord sur la taille de something.

    La mise à jour de la lib n'est pas ABI compatible avec la version précédente et pourtant ça link bien. Sur cet exemple c'est bénin mais en pratique ça cause de sacrés problèmes. Et il ne suffit pas d'ajouter ou supprimer des champs pour causer des soucis, rien que changer l'ordre pose problème.