Falsche Konvertierung von Double zu QString in Qt auf ARM

8

Ich habe Qt 4.4.3 für ARMv5TE gebaut. Ich versuche ein double in ein QString zu konvertieren:

%Vor%

aber seltsame Ausgabe:

%Vor%

Wie bekomme ich die richtige Zeichenfolge?

    
Renat Zaripov 13.04.2012, 13:57
quelle

2 Antworten

8

Dies scheint eine Art Endianess-Problem zu sein, aber nicht Ihr einfaches Van-Big-Endian-gegen-Little-Endian-Problem. ARM verwendet manchmal eine ungewöhnliche Byte-Reihenfolge für double . Aus "Handbook of Floating-Point Arithmetic" von Jean-Michel Muller, et al .:

  

... die Nummer mit der doppelten Genauigkeit, die am nächsten ist    -7.0868766365730135 x 10^-268 wird durch die Bytefolge codiert    11 22 33 44 55 66 77 88 im Speicher (von der niedrigsten zur höchsten   ein) auf x86 und Linux / IA-64 Plattformen (sie sollen sein    little-endian ) und von 88 77 66 55 44 33 22 11 auf den meisten PowerPC-Plattformen (sie werden als big-endian bezeichnet). Einige Architekturen, wie z   als IA-64, ARM und PowerPC wird gesagt, bi-endian zu sein. d.h. sie können   sei entweder Little-Endian oder Big-Endian abhängig von ihren   Konfiguration.

     

Es gibt eine Ausnahme: einige ARM-basierte Plattformen. ARM-Prozessoren   habe traditionell den Fließkomma-Beschleuniger (FPA) verwendet   Architektur, wo die Zahlen mit doppelter Genauigkeit zerlegt werden   zwei 32-Bit-Wörter in der Big-Endian-Reihenfolge und gespeichert nach der   Endlichkeit der Maschine, d. h. Little-Endian im Allgemeinen, was bedeutet   dass die obige Zahl durch die Sequenz 55 66 77 88 11 22 33 44 codiert ist. ARM hat vor kurzem eine neue Architektur für Gleitkomma eingeführt   arithmetisch: Vektor Gleitkomma (VFP), wo die Wörter gespeichert werden   in der nativen Byte-Reihenfolge des Prozessors.

Wenn in einer Big-Endian-Byte-Reihenfolge betrachtet wird, hat M_PI eine Repräsentation, die wie folgt aussieht:

%Vor%

Die große Anzahl von 8.6192e+97 wil hat eine Repräsentation, die wie folgt aussieht:

%Vor%

Wenn Sie genau hinsehen, werden die zwei 32-Bit-Wörter vertauscht, aber die Byte-Reihenfolge innerhalb der 32-Bit-Wörter ist die gleiche. Offensichtlich scheint das "traditionelle" Doppelpunktformat von ARM die Qt-Bibliothek zu verwirren (oder die Qt-Bibliothek ist falsch konfiguriert).

Ich bin mir nicht sicher, ob der Prozessor das traditionelle Format verwendet und Qt erwartet, dass es im VFP-Format vorliegt, oder wenn die Dinge umgekehrt sind. Aber es scheint eine dieser beiden Situationen zu sein.

Ich bin mir auch nicht sicher, wie ich das Problem genau beheben kann - ich denke, es gibt eine Möglichkeit, Qt so zu bauen, dass es korrekt funktioniert.

Das folgende Snippet wird Ihnen zumindest sagen, welches Format für double der Compiler verwendet, was Ihnen helfen kann einzugrenzen, was in Qt geändert werden muss:

%Vor%

Ein einfacher Little-Endian-Rechner zeigt Folgendes an:

%Vor%

Update mit ein bisschen mehr Analyse:

Im Moment kann ich kein echtes Debugging durchführen (ich habe im Moment noch nicht einmal Zugriff auf meine Workstation), aber ich schaue mir die Qt-Quelle an, die auf Ссылка hier ist eine zusätzliche Analyse:

Es sieht so aus, als ob Qt die Funktion QLocalePrivate::doubleToString() in qlocale.cpp aufruft, um eine double in eine alphanumerische Form zu konvertieren.

Wenn Qt mit QT_QLOCALE_USES_FCVT definiert ist, verwendet QLocalePrivate::doubleToString() die Funktion fcvt() der Plattform, um die Konvertierung durchzuführen. Wenn QT_QLOCALE_USES_FCVT nicht definiert ist, endet QLocalePrivate::doubleToString() mit dem Aufruf von _qdtoa() , um die Konvertierung durchzuführen. Diese Funktion untersucht die verschiedenen Felder von double direkt und scheint davon auszugehen, dass double in einer strikten Big-Endian- oder Little-Endian-Form vorliegt (z. B. mit den Funktionen getWord0() und getWord1() ) niedriger und hoher Wert von double ).

Siehe Ссылка und Ссылка oder Ihre eigene Kopie der Dateien für Details.

Angenommen, Ihre Plattform verwendet die traditionelle ARM FPA-Repräsentation für double (wobei die 32-Bit-Hälften von double in Big-Endian-Reihenfolge gespeichert sind, unabhängig davon, ob das Gesamtsystem Little-Endian ist), I Ich denke, du musst Qt mit der QT_QLOCALE_USES_FCVT definieren. Ich glaube, dass Sie nur die Option -DQT_QLOCALE_USES_FCVT an das configure-Skript übergeben müssen, wenn Sie Qt erstellen.

    
Michael Burr 13.04.2012, 23:10
quelle
4

Derselbe Code erzeugt eine korrekte Ausgabe auf einem x86-Computer (unter Windows XP) mit Qt 4.7.0.

Ich sehe die folgenden Möglichkeiten für die Ursache des Problems:

  • Ein Fehler, der vielleicht in einer neueren Version von Qt
  • behoben wurde
  • Beim Erstellen von ARM
  • ist ein Fehler aufgetreten

Ich fand diesen Forenbeitrag bei einem ähnlichen Problem, das davon ausgeht, dass es sich um ein Konvertierungsproblem für große / kleine Endiane handeln könnte.

Ich kann nicht sagen, wie ich das beheben kann, da ich überhaupt nicht mit ARM vertraut bin, aber vielleicht hilft Ihnen diese Information trotzdem.

    
Tim Meyer 13.04.2012 14:54
quelle

Tags und Links