33 votes

Tester le code C++ pour l'indépendance endienne

Comment puis-je tester ou vérifier l'indépendance endienne d'un code C++ ? C'est déjà implémenté, je voudrais simplement vérifier qu'il fonctionne à la fois sur les plateformes little-endian et big-endian.

Je pourrais écrire des tests unitaires et les exécuter sur les plateformes cibles, mais je n'ai pas le matériel nécessaire. Peut-être des émulateurs ?

Peut-on effectuer des contrôles au moment de la compilation ?

4 votes

@0A0D, ce n'est pas un dup. Cette question portait sur la manière de détecter l'endiannité de la plate-forme actuelle. L'OP veut vérifier si son code fonctionne correctement sur les plateformes BE et LE.

0 votes

@0A0D/@Chris : vous devez relire la question.

1 votes

@0A0D : Il ne s'agit pas de détecter l'endiveté de la plateforme. La question est de savoir comment être sûr qu'un code donné dépend de l'endianness.

17voto

Paul R Points 104036

Si vous avez accès à un Mac basé sur x86, vous pouvez profiter du fait que Mac OS X intègre l'émulation PowerPC et que les outils de développement prennent en charge à la fois x86 (little endian) et PowerPC (big endian). Ceci vous permet de compiler et d'exécuter un exécutable big et little endian sur la même plate-forme, par exemple

$ gcc -arch i386 foo.c -o foo_x86 # build little endian x86 executable
$ gcc -arch ppc foo.c -o foo_ppc  # build big endian PowerPC executable

Après avoir construit les exécutables big endian et little endian, vous pouvez alors exécuter les tests unitaires dont vous disposez sur les deux, ce qui permettra de détecter certaines catégories de problèmes liés à l'endiannisme, et vous pouvez également comparer toutes les données générées par les exécutables (fichiers, paquets réseau, etc.) - elles devraient évidemment correspondre.

1 votes

Solution plutôt coûteuse du problème si vous n'avez pas de Mac. Le downvote n'est pas de moi.

2 votes

@Kirill (et le votant anonyme) : notez que j'ai spécifiquement dit "si vous avez accès à un Mac" - il y a de nombreuses façons d'avoir accès à un Mac pour une période de test sans en acheter un (bien que, comme cela a déjà été souligné, un Mac Mini d'occasion bon marché coûte très peu sur eBay).

0 votes

@Paul : savez-vous s'il est possible de compiler pour l'architecture PPC sur une machine x86 comme l'inverse ? Peut-être que je n'ai pas bien formulé ma question...

12voto

Ken Bloom Points 27197

Vous pouvez configurer un environnement d'exécution dans l'endianness opposé en utilisant qemu . Par exemple, si vous avez accès à du matériel amd64 ou i386 little-endian, vous pouvez configurer qemu pour émuler une plateforme Linux PowerPC et y exécuter votre code.

7voto

sehe Points 123151

6voto

Lindydancer Points 13353

Je suggérerais d'adapter une technique de codage qui évite complètement le problème.

Tout d'abord, vous devez comprendre dans quelle situation un problème d'endianage se produit. Ensuite, il faut soit trouver un moyen d'écrire ce code endiablé, soit isoler le code.

Par exemple, un problème typique où des problèmes d'endianage peuvent se produire est lorsque vous utilisez des accès à la mémoire ou des unions pour sélectionner des parties d'une valeur plus grande. Concrètement, il faut éviter :

long x;
...
char second_byte = *(((char *)&x) + 1);

Au lieu de cela, écrivez :

long x;
...
char second_byte = (char)(x >> 8)

La concaténation, c'est l'une de mes préférées, car beaucoup de gens ont tendance à penser qu'on ne peut la faire qu'en utilisant des astuces étranges. Ne faites pas ça :

union uu
{
  long x;
  unsigned short s[2];
};
union uu u;
u.s[0] = low;
u.s[1] = high;
long res = u.x;       

Écrivez plutôt :

long res = (((unsigned long)high) << 16) | low

1voto

Doug T. Points 33360

Je pourrais écrire des tests unitaires et les exécuter sur les plates-formes cibles, mais je n'ai pas le matériel nécessaire.

Vous pouvez configurer votre conception de manière à ce que les tests unitaires soient faciles à exécuter, indépendamment de la présence réelle de matériel. Vous pouvez le faire en utilisant l'injection de dépendances. Je peux faire abstraction de choses comme les interfaces matérielles en fournissant une classe d'interface de base à laquelle le code que je teste se réfère.

class IHw
{
public:
    virtual void SendMsg1(const char* msg, size_t size) = 0;
    virtual void RcvMsg2(Msg2Callback* callback) = 0;
     ...
};

Ensuite, je peux avoir l'implémentation concrète qui parle réellement au matériel :

class CHw : public IHw
{
public:
    void SendMsg1(const char* msg, size_t size);
    void RcvMsg2(Msg2Callback* callback);
};

Et je peux faire une version test de la souche :

class CTestHw : public IHw
{
public:
    void SendMsg1(const char* msg, size_t);
    void RcvMsg2(Msg2Callback* callback);
};

Alors mon code réel peut utiliser le Hw concret, mais je peux le simuler dans le code de test avec CTestHw.

class CSomeClassThatUsesHw
{
public:
   void MyCallback(const char* msg, size_t size)
   {
       // process msg 2
   }
   void DoSomethingToHw()
   {
       hw->SendMsg1();
       hw->RcvMsg2(&MyCallback);
   }
private:
    IHw* hw; 
}

0 votes

Parfois, je peux écrire mon code de manière à ce qu'il ne dépende pas d'un endiannage spécifique et qu'il fonctionne sur toutes les plateformes matérielles. Je préfère cela aux implémentations spécifiques au matériel, lorsque c'est possible, car cela permet de maintenir moins de code.

0 votes

Bien sûr, mais l'injection de vos conversions d'endianness en fonction de la dépendance ? Ce n'est pas aller un peu loin ?

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