• Apfeltalk ändert einen Teil seiner Allgemeinen Geschäftsbedingungen (AGB), das Löschen von Useraccounts betreffend.
    Näheres könnt Ihr hier nachlesen: AGB-Änderung
  • Viele hassen ihn, manche schwören auf ihn, wir aber möchten unbedingt sehen, welche Bilder Ihr vor Eurem geistigen Auge bzw. vor der Linse Eures iPhone oder iPad sehen könnt, wenn Ihr dieses Wort hört oder lest. Macht mit und beteiligt Euch an unserem Frühjahrsputz ---> Klick

Big Endian sorgt für korrupte Dateien

  • Ersteller GoaSkin
  • Erstellt am

GoaSkin

Gast
Ich programmiere gerade ein Programm, das dazu dienen soll, GUI-gesteuert Plugins für ein Spiel zu erzeugen und lege dabei Wert auf Plattformtransparenz.

Ich habe mich dazu entschlossen, die QT-Bibliothek zu nutzen und XCode als Entwicklungsumgebung zu nutzen. Soweit so gut, der Quellcode lässt sich unter Windows, OSX und Linux compilieren und das Programm läuft --scheinbar-- auf allen Plattformen einwandfrei. Das dachte ich bis vor kurzem zumindest.

Ich habe nun das Programm einmal auf einem G4 compiliert und ausgeführt und wunderte mich die ganze Zeit, daß die erzeugten Dateien korrupt sind. Nach einigen Analysen stellte ich fest, daß sämtliche Ausgabevariablen in der Datei in umgekehrter Byte-Reihenfolge zu lesen sind. Die Endian-Problematik war eine schnelle Vermutung, die sich auch bestätigte.

In der Export-Funktion wird gemäß Spezifikation ein langer Array mit allen notwendigen Daten erzeugt und dieser anschließend in eine Datei geschrieben. PPC-Rechner schreiben alle einzelnen Variablen verkehrt herum in diesen Array rein.

Das Netz verrät viel, mit welchen Funktionen sich Byte-Reihenfolgen umdrehen lassen, wobei ich das kaum für praktikabel halte. Unter anderem wird eine Header-Datei mit Funktionen zur Endian-Konvertierung mit dem Ziel, Netzwerkdaten umzudrehen genannt, die man auch nutzen kann, um einzelne Variabeln zu drehen. Das wäre in diesem Fall viel Arbeit, würde den Quellcode sehr unübersichtlich machen und für 64Bit-Integer müsste ich mir noch eine Lösung einfallen lassen.

Gibt es keine Lösung (z.B. ein Makro), mit der man im Quelltext nicht permanent darauf achten muß, daß ein PPC im Big-Endian-Modus arbeitet und dafür sorgt, daß einzelne Werte grundsätzlich so in einen Array eingetragen werden, als wäre es eine Little-Endian-Maschine?

Da ja ein PPC angeblich auch den Little-Endian-Modus beherrscht - gäbe es ggf. die Möglichkeit, dafür zu sorgen, daß das Programm im Little-Endian-Modus läuft?
Unter Linux (PPC) kann man das gcc-Flag -m little setzen. Unter Darwin kennt der GCC das nicht.
 

tjp

Altgelds Küchenapfel
Registriert
07.07.04
Beiträge
4.059
Gibt es keine Lösung (z.B. ein Makro), mit der man im Quelltext nicht permanent darauf achten muß, daß ein PPC im Big-Endian-Modus arbeitet und dafür sorgt, daß einzelne Werte grundsätzlich so in einen Array eingetragen werden, als wäre es eine Little-Endian-Maschine?
Wenn Du ständig Werte in Arbeitsspeicher in der falschen Reihenfolge ablegst ist die Performance unterirdisch. Füge eine saubere Serialisierungsschicht in die Software ein, so daß das kein Problem mehr ist.
Da ja ein PPC angeblich auch den Little-Endian-Modus beherrscht
Das wurde vom OS vorgegeben, und außer NT hat es nie ein OS auf PPC genutzt. Die neuen PPCs kann man zum Teil nur noch im BigEndian Modus betreiben.
 

Amin Negm-Awad

Süsser Pfaffenapfel
Registriert
01.03.07
Beiträge
665
Nein, die gesamte Zeit in der nicht-nativen Byte-Reihenfolge zu arbeiten, wäre dämlich. Vor dem Schreiben gleich eine swap-feste Library zu verwenden, oder falls es die nicht gibt, wie von tjp vorgeschlagen selbst eine Schicht dazwischen einzuführen, ist nicht unübersichtlich. Sie ist sogar transparent, also unsichtbar.

Wenn du einen Text in Englisch verfassen sollst, überlegst du dir doch nicht die Strukturierung des Textes in deinem Kopf auf englisch, bloß weil das mal die "Ziel-Sprache" ist. Du denkst auf deutsch und übersetzt es ins Englische, wenn es notwendig ist.
 

below

Purpurroter Cousinot
Registriert
08.10.06
Beiträge
2.858
Wenn ich mich aus dem Fenster lehnen darf:

Die richtige Antwort ist: "Es kommt darauf an". Wenn man Byte Order swapping braucht, dann ist immer irgendwo ein Bottleneck. Komplexe Strukturen kann man nur mit einem bestimmten Aufwand drehen.

Dann ist also die Frage: Wann brauche ich die Performance? Bei mir müssen die Daten häufig im Bedarfsfall im Ausgabeformat fix und fertig vorliegen (z.B. DMA), also wandele ich sie direkt wenn ich sie bekomme.
Bei den meinsten GUI Applikationen würde ich das aber erst direkt vor der Ausgabe in Datei, bzw. bem Einlesen machen.

Alex
 

Amin Negm-Awad

Süsser Pfaffenapfel
Registriert
01.03.07
Beiträge
665
Du lehnst dich überhaupt nicht aus dem Fenster. Wenn du sie in den DMA-Bereich legst, "verlassen Sie dein Programm" so als ob du sie auf Platte schreiben würdest. Und wie hier vorgeschlagen wandelt man sie dann um.

Wenn du allerdings selbst noch auf diesen Daten arbeiten möchtest, wirst du das sicher nicht in nicht nativer Bytefolge machen, auch dann nicht, wenn die Umwandlung komplex ist.

Bliebe allenfalls noch der Fall, dass du die Daten "umgekehrt" herein liest und ebenso wieder rausschicken musst. Hier hast du offenkundig überhaupt kein Problem mit Endianess.
 

tjp

Altgelds Küchenapfel
Registriert
07.07.04
Beiträge
4.059
Dann ist also die Frage: Wann brauche ich die Performance? Bei mir müssen die Daten häufig im Bedarfsfall im Ausgabeformat fix und fertig vorliegen (z.B. DMA), also wandele ich sie direkt wenn ich sie bekomme.
Ich nehme stark an, daß Du Dich hierbei auf Treiber-Entwicklung oder andere Low-Level Aspekte beziehst bei denen es notwendig ist auf irgend welche Hardware-Register o.ä. zuzugreifen. Leider muß man sich dabei mit viel Hardware auseinandersetzen, die nun einmal Daten im Little Endian Format erwartet. Das ist auch eine Folge der Intel Dominanz. Intel Hardware ist schon immer im Little Endian Format gewesen.

Immer dann wenn Daten aus dem Programm irgend wo hinaus transferiert werden, muß man sich mit der Thema Serialisierung auseinandersetzen, es ist ja nicht nur die Endianness Problematik sondern auch Padding Bytes sind da ein Thema. Wenn man richtig serialisiert, dann umgeht man all diese Probleme.
 

below

Purpurroter Cousinot
Registriert
08.10.06
Beiträge
2.858
Ich nehme stark an, daß Du Dich hierbei auf Treiber-Entwicklung oder andere Low-Level Aspekte beziehst bei denen es notwendig ist auf irgend welche Hardware-Register o.ä. zuzugreifen. Leider muß man sich dabei mit viel Hardware auseinandersetzen, die nun einmal Daten im Little Endian Format erwartet.
Richtig, ich beziehe mich hier auf Treiber etc. Zu Little Endian: Nicht ausschliesslich, es gibt Sachen, die gibt es gar nicht,zum Beispiel USB Geräte bei denen der Header (natürlich) little Endian, die Payload aber Big Endian sein muss.

Wenn man richtig serialisiert, dann umgeht man all diese Probleme.
Beziehst Du Dich da jetzt auch auf meinen LowLevel Kram?

Alex
 

tjp

Altgelds Küchenapfel
Registriert
07.07.04
Beiträge
4.059
Beziehst Du Dich da jetzt auch auf meinen LowLevel Kram?

Alex
Nur bedingt, denn es kann aus Geschwindigkeitsgründen durchaus angebracht sein, von dieser Regel abzuweichen, nur würde ich das nicht ohne triftigen Grund tun. Treiberentwicklung ist so ein Problembereich bei normalen Anwendungen sehe ich da aber eher selten Bedarf.
 

Amin Negm-Awad

Süsser Pfaffenapfel
Registriert
01.03.07
Beiträge
665
Beziehst Du Dich da jetzt auch auf meinen LowLevel Kram?
Alex
Na, bedenke dass man zwar Serialisierung meist im Kontext mit Streams verwendet. Aber das ist nicht zwingend. Serialisierung bedeutet (im Wortsinne wie im technischen Sinne) lediglich, dass du einen Graphen in serielle, also abfolgende Anordnung bringst. Dabei spielt es keine Rolle, ob das eine Datei ist oder ein DMA-Bereich. Was du da machst ist auch Serialisierung.

Ganz wichtig ist dies ja auch im Zusammenhang mit Versand von Daten im Netzwerk.