"A big Little Endian Problem" oder sowas in der Art



  • Hallo zusammen,

    ich hab da ein doofes Problem. Und zwar habe ich folgenden Code.

    UInt l_tmpValue     = puiLength->value;
                // puiLength->value    = l_tmpValue;
    
                UInt l_tmpMaxLength = stInnerArrCnt.uiMaximumLength;
                //stInnerArrCnt.uiMaximumLength = l_tmpMaxLength;
    
                if ( l_tmpValue > l_tmpMaxLength )
                {
                  return ERROR;              
                }
    
                if ((UInt)stInnerArrCnt.uiMaximumLength < (UInt)puiLength->value)
                {
                  return ERROR;
                }
    

    In meine erste IF Abfrage springt er nicht rein, in die zweite schon, obwohl die Variablen von "aussen" nicht angefasst werden. Auch der Debugger (watch) zeigt mir die gleichen Werte für den Zeiger und für die UInt's.

    Das ganze könnte irgendwie ein little bzw. big endian problem sein, denn wenn ich mir den assembler code ansehe, dass holt der mir irgendwie die falschen höherwertigen bits, als er soll. Oder da steht müll im speicher, der da nicht stehen soll (aber immer der gleiche). leider bin ich kein c experte und weiss nicht wo man ein solches problem anpacken muss.

    vielleicht kann mir ja jemand helfen.
    Grüße Nils



  • Normalerweise sollte es innerhalb eines Programms keine Endianess-Probleme geben, höchstens mit negativen Werten. In welcher Größenordnung liegen denn die Variablen, die du vergleichst?



  • die eine ist 0 und die andere 6, also ein überlauf oder sowas sollte es nicht geben. komischerweise kann ich die werte nachdem ich sie expliziet in eine UInt reingeschrieben hab wieder in den "Zeiger" kopieren und dann klappts.

    Im Debugger sieht auch alles ganz gut aus, nur die assembler ansicht kommt mir komisch vor und die ist ja auch das, was zählt oder? Könnte so etwas ein Compiler Fehler sein (verwende den GCC)?



  • Was kommt denn heraus, wenn du die Cast's in der zweiten Abfrage weglässt?

    (und btw: welchen Typ haben eigentlich die verwendeten Variablen?)



  • Die Typen sind UInt (=WORD), der Cast ist also eigentlich unsinnig, war nur ein Klammern an den Strohhalm. Beim weglassen bekomm ich genau die gleichen Ergebnisse (habs grad nochmal probiert).



  • Also eine Kleinigkeit aus dem Assembler Code vll noch.

    die Zeile

    cmp r3, r2

    vergleicht die Werte 06000000 und 00000006. Aber eigentlich müsste er ja 00000000 und 00000006 vergleichen.



  • Wenn du nicht weißt, wo da ein Endianness-Problem herkommt, dann ist es auch keins. Sowas tritt nur in der Kommunikation mit andereren Plattformen auf, evtl. auch indirekt durch binäre Dateiformate o.ä. Du solltest auch IHMO nicht zuerst davon ausgehen, dass dein Compiler verbuggt ist, und im Assembler-Code rumkramen. Beschreib doch mal bitte dein Problem etwas genauer. Ich sehe da zunächst mal zwei verschiedene Bedingungen, einmal kleiner, einmal größer, so dass es nicht weiter verwunderlich sein sollte, dass nur eine davon zutrifft.



  • Das mit dem kleiner und größer ist nur mal aus reiner verzweiflung entstanden. Wenn du genau hinschaust, dann sind auch die Werte verdreht, also isses im Endeffekt wieder die gleiche Aussage.



  • was ist dieses 'puiLength'?
    falls das ungefähr sowas ist:

    irgendeintyp irgendwelche_daten[irgendeine_anzahl];
    uiLength *puiLength = (uiLength*)irgendwelche_daten;  // <<- sowas geht oft schief
    

    dann könnt's schon sein, dass er zickt...
    🙂



  • Also sieht schon verdammt danach aus:

    BasicStruct_UInt* puiLength = (BasicStruct_UInt*) pstPar->pDest;
    

    naja ich hab kein Array. Woran denkst du denn, dass es liegen könnte?



  • Und was für einen Typ hat 'pstrPar->pDest'? (wenn das schon ein Zeiger auf ein 'BasicStruct_UInt' ist, erübrigt sich der Cast, andernfalls könnten dort die selben Probleme auftreten wie bei einem Array - irgendwelche (in anderem Zusammenhang gebrauchte) Daten werden als BasicStruct neu interpretiert)



  • also pstrPar ist so ein struct

    typedef struct {
      CommBufferPointer pstSource;
      USInt* pDest;
      UInt uiBufferlength;
    } Deser_ParStruct;
    

    leider wurde der Code von einem Code Generator erstellt, deswegen sind manchmal vielleicht unschöne Sachen drin.

    Und hier noch der vollständigkeit halber.

    typedef struct {
      UInt value;
    }  BasicStruct_UInt;
    

    dass das ganze als struct sein muss, liegt irgendwie am alignment des contollers und der damit resultierenden GAPS bei der deserialisierung.

    das beide vom typ UInt sind, war dann wohl glatt gelogen von mir vorhin, aber war mir irgendwie sicher. Naja "meinen" Fehler finde ich trotzdem nicht.



  • Sehe ich das richtig, daß pDest ein USInt ist? (und wofür steht das 'S'? short?)



  • jop short sollte werte von 0...255 drin haben.



  • Und da hast du auch schon das Problem - effektiv hast du ein short-Array als int-Array interpretiert, dadurch werden (short=16 Bit, int=32 Bit) jeweils zwei Array-Elemente zu einem int-Wert zusammengepackt. Die einzige Lösung, die ich dir empfehlen kann, ist: vermeide Typ-Umwandlungen, wo immer es geht (gerade bei Pointern läuft das schnell aus dem Ruder) - du kannst besser direkt auf deine Daten zugreifen, da weiß der Compiler höchstwahrscheinlich besser als du, wie er mit verschiedenen Typen umgehen muß.

    (das sind zwar ein paar Indirektionen mehr, aber dafür ist es weniger fehleranfällig)



  • erzähl mehr von dem, was du da bastelst.
    - was ist das für ein controller/prozessor?
    - woher komen die daten, auf die du da zugreifsen willst?
    wahrschinlich sind doch noch irgendwo endian-dreher drin...
    🙂



  • also es ist ein keil mcb2140 board mit usb anschluss und daher kommen auch die daten. controler. ist ein arm. kompiliert wird mit den optionen

    -c -gdwarf-2 -MD -O0 -mapcs-frame -mcpu=arm7tdmi -w -mthumb-interwork -mlittle-endian
    

    die usb seite war herstellerseitig (hitex) schon vorimplementiert. dann kamen unsere geräteseitigen funktionen dazu und alles ging auch wunderbar, bis auf diese eine stelle.



  • du machst ja little endian auf dem arm, das sollre sich mit dem pc vertragen.
    macht usb vielleicht irgendwelche dataframes die möglicherweise big-endian werte enthalten?
    alignment könnte's auch sein. ein arm kann z.b. nicht 2-bytig auf ungerade adressen zugreifen (er springt dann in'n exception-handler, was bei dir offensichtlich nicht passiert) aber die structs müssen trotzdem aligned angelegt werden. wenn du jetzt 'nen type-cast von einer strukt in eine andere machst, dann geht das mit ziemlicher sicherheit voll daneben...
    musste irgendwie debuggen.
    z.b. hexdumps ausgeben usw.
    haste 'nen jlink-adapter oder sowas?
    dann nimm z.b. die testversion vom IAR (EWARM).
    der debugger, der dabei ist, ist spitze...



  • ich hab eigentlich alles was dazugehört. jtag debugger von hitex (Tantino). die werte im speicher sehen auch alle richtig aus 😞 also eigentlich sollte alles stimmen. tuts aber leider nicht 😞



  • Nils_Langner schrieb:

    ich hab eigentlich alles was dazugehört. jtag debugger von hitex (Tantino). die werte im speicher sehen auch alle richtig aus 😞 also eigentlich sollte alles stimmen. tuts aber leider nicht 😞

    na, damit solltestes aber finden.
    laufen dabei noch irgendwelche interrupts? vielleicht zerbrutzelt dir irgendwas die daten?


Anmelden zum Antworten