Forum Programmation.autre warning: cast from pointer to integer of different size

Posté par  .
Étiquettes : aucune
0
16
mai
2006
Bonjour j'ai un petit problème lors de la compilation. Je l'ai posté sur ce site dans le forum mandriva (lien ici : http://linuxfr.org/forums/14/16571.html). Je l'ai reposté ici puisqu'il s'agit maintenant d'un Pb de programmation.
Je reçoit l'alarme suivante : warning: cast from pointer to integer of different size.
J'ai bien compris qu'il s'agit d'un problème de migration vers 64bits mais que faire ?
  • # Problème de programmation C

    Posté par  . Évalué à 2.

    1) Quand on écrit des liens URL dans les messases de linuxfr, il faut faire attention à détacher toute ponctuation du lien; la parenthèse fermante et le point accolés à ton lien le rendent invalide ( http://linuxfr.org/forums/14/16571.html ).

    2) Il s'agit d'un problème de programmation C. Je n'ai pas réussi à voir les sources (d'après le rapport de compilation, c'est le plugin VC qui plante, je ne l'ai pas trouvé sur le site); mais le message est clair: les gens qui ont codé ce plugin ont, à plusieurs moments, fait un cast d'une valeur de type pointeur vers un type entier qui n'est pas assez grand.
    En pratique, ça peut ressembler à:
    float f = 5.0f;
    float *p = &f
    int i;
    i = (int) p;

    La conversion entre un pointeur et un type entier est, au sens de la norme C, implementation-defined, ce qui veut dire que le résultat d'une telle conversion peut varier d'une plate-forme à une autre.

    En particulier, le domaine de valeurs d'un type pointeur peut ne pas entrer dans le domaine de valeurs d'un type entier arbitraire; il peut y avoir plus de valeurs possibles pour un float* que pour un int sur une machine, pour reprendre mon exemple (je ne sais pas si ça existe, c'est juste un exemple de ce qui peut arriver), donc il y aura une perte d'information possible; d'où l'avertissement que t'envoie ton compilateur.

    La solution propre serait de ne pas faire de cast entre valeur de type pointeur et un type entier. Cela augmenterait largement la portabilité du code. Mais, si cela est trop difficile, ou risque de casser une interface quelconque (ce qui montrerait, AMHA, une erreur de conception assez grosse), il y a une autre solution: utiliser un type entier adapté à ce genre de choses. La norme C99 définit les types optionels intptr_t et uintptr_t (7.18.1.4 du n1124.pdf) qui sont faits exactement pour ça... La norme garantit que, quand l'implémentation les fournit, les conversions void* -> [u]intptr_t -> void* se font sans perte(*).

    Par ailleurs, les tailles (ou plus précisément les domaines de valeurs) des types pointeurs ne sont pas contraintes, ce qui fait qu'un pointeur void* n'a pas forcément la même taille qu'une pointeur sur int*, par exemple... Il faut donc faire attention à ne caster que du void* vers les [u]intptr_t.

    (*) Plus précisément, la norme ne garantit qu'une comparaison entre le résultat de la conversion void* -> [u]intptr_t -> void* et la valeur de départ renverra une égalité. (i.e. p == (void*)(intpre_t) p , si p est de type void*).
    • [^] # Re: Problème de programmation C

      Posté par  . Évalué à 1.

      Ok, bien noté pour la remarque du 1).

      Voici le lien pour obtenir le source : http://www.multimedia.cx/VC1_reference_decoder_release6.zip
      Merci pour tes remarques et tes conseils éclairées.
      • [^] # Re: Problème de programmation C

        Posté par  . Évalué à 2.

        Pour vc1decbit.c: il s'agit d'une macro utilisée pour tracer des messages de debug (DEBUG2) qui est en cause, ou plutôt son utilisation. Note qu'en mode non-debug, cette macro est définie par une expression nulle, le warning n'apparaît donc qu'en mode DEBUG (plus précisément, quand la macro NDEBUG est definie).
        Exemple, ligne 473:
        DEBUG2(vc1DEBUG_BIT, "Initialise Bitstream Start=0x%08x Length=%d\n",
        (int)pBuffer, Length);

        Sans aller voir la fonction qui est utilisée, on sent qu'elle doit être basée sur uen fonction de la famille de printf() (à vérifier). Si c'est le cas, alors ils utilisent le format %x pour afficher en hexadécimal les valeurs du pointeur pBuffer. Vu qu'il ne s'agit que d'un message de debug, on peut je pense changer la ligne (qui, de toute façon, invoque au mieux un comportement implementation-defined) en:
        DEBUG2(vc1DEBUG_BIT, "Initialise Bitstream Start=%p Length=%d\n",
        (void *)pBuffer, Length);

        Ainsi, on ne risque pas de warning, et c'est portable. L'affichage sera juste un peu différent, mais si c'est juste pour le debug, changer le format d'affichage ne devrait pas gêner outre mesure.
        Note que le cast en void * est nécessaire.

        Ce n'est pas un problème spécifique à un passage de 32 à 64 bits, mais juste une utilisation de propriétés implementation-defined (voire undefined) de gestion des pointeurs qui a été mis en évidence par un changement d'architecture...

        Pour vc1decblk.c: le problème vient de:
        vc1recon.h:
        void vc1RECON_ReconstructMB (const HWD16 pTCoefs[6][64], const UBYTE8
        pPredBlk[6][64], vc1_sReferencePicture *pRefPic, vc1_sPosition *pPosition, vc1_eProfile eProfile)

        vc1decblk.c:
        vc1_eResult vc1DECBLK_DecodeBlockLayer(
        vc1DEC_sState * pState,
        vc1DEC_sBitstream * pBitstream)
        {
        HWD16 TCoefs[6][64] = {{0}};
        UBYTE8 PredBlk[6][64];
        /* ... */
        vc1RECON_ReconstructMB(TCoefs,
        PredBlk,
        pState->pCurrentRef,
        pPosition,
        pState->sSeqParams.eProfile);

        Ainsi, les 2 premiers paramètres passés à vc1RECON_ReconstructMB sont définis comme des tableaux, mais le passage en paramètre d'un tableau le convertit implicitement en pointeur. Comme il s'agit de tableaux multi-dimensionels, 6.5.2.1 dit que TCoefs est converti en un pointeur vers HWD16 [64], alors que la fonction attend un pointeur vers const HWD16 [64]. Pour vc1recon.c: les lignes 110 et 120 ont le même problême que pour vc1decblk.c: un assignation de pointeurs de type diférents, la différence étant due au qualificateur const.

        Apres une petite recherche sur comp.lang.c, j'ai trouvé dans la FAQ ceci: http://c-faq.com/ansi/constmismatch.html
        Pour résumer, le moyen de contourner le problème est de faire un cast. Pas propre, tout ça...
        Ou alors il faudrait enlever le const du prototype des fonctions en cause. Cette dernière solution aurait au moins le mérite de ne plus causer de problème; mais je supose que les const sont là pour optimiser un chouia le code. On peut les virer au moins pour commencer (il vaut mieux faire du code qui marche et ensuite l'optimiser, que créer un code optimisé et ensuite le corriger).

        Note que la ligne 120 de vc1recon.c pose un autre problème: un paramètre formel de la fonction, de type tableau multidimensionel (donc, en réalité, pointeur sur tableau), est réassigné ! C'est légal du point de vue du C (pour autant que je sache), mais c'est très moche...
        • [^] # Re: Problème de programmation C

          Posté par  . Évalué à 1.

          Ok merci pour l'explication détaillée. J'ai réussi a compiler l'ensemble avec de nombreux avertissements. Ca ne fonctionne pas, mais c'est peut-être un problème de config/déclaration entre ffmpeg et kaffeine. Je cherche ...

          Je veux pas être mauvaise langue mais le source de base c'est du microsoft !
          Ceci explique peut-être celà ...

          Merci encore
          Pascal

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.