Pointer auf eingebettete Geräte werfen

7

Ich bin auf ein seltsames Problem gestoßen, als ich Pointer auf einem eingebetteten 32-Bit-System ( redbee econotag ), das contiki OS um genau zu sein).

%Vor%

Ausgabe auf meinem Computer:

%Vor%

Ausgabe auf dem eingebetteten Gerät:

%Vor%

Mein Computer verhält sich so, wie ich es erwarte, aber das eingebettete Gerät scheint sich am Ende des Wortes zu bewegen. Warum passiert das?

    
Baarn 25.12.2012, 16:50
quelle

5 Antworten

13

Ihr Ziel „redbee econotag“ als ARM7 angegeben, die ARMv4 Architektur. ARMv4 bietet keine unaligned Speicherzugriff wie ein ARMv7 oder einer Intel-Maschine.

Zitiert von ARM Dokumentation :

  
    

Auf ARMv4 und ARMv5 Architekturen und auf der ARMv6-Architektur je nachdem, wie es konfiguriert ist, muss darauf geachtet werden, wenn nicht ausgerichteten Daten im Speicher zugreifen, damit unerwartete Ergebnisse zurückgegeben werden. Wenn beispielsweise ein herkömmlicher Zeiger verwendet wird, um ein Wort im C- oder C ++ - Quellcode zu lesen, erzeugt der ARM-Compiler Assemblersprachcode, der das Wort unter Verwendung eines LDR-Befehls liest. Dies funktioniert wie erwartet, wenn die Adresse ein Vielfaches von vier ist, beispielsweise wenn sie auf einer Wortgrenze liegt. Allerdings , wenn die Adresse nicht ein Vielfaches von vier ist, gibt die LDR ein gedrehtes Ergebnis eher als eine echte unaligned Wort Last durchführen. Im Allgemeinen ist diese Drehung nicht das, was der Programmierer erwartet .

  
    
auselen 26.12.2012, 02:14
quelle
13

Mit diesem Code brechen Sie die strenge Aliasing-Regel: Auf das Objekt, auf das point zeigt, wird durch einen lvalue-Ausdruck zugegriffen, der uint32_t type hat.

  

C11 (n1570), § 6.5 Ausdrücke
  Auf einen gespeicherten Wert eines Objekts darf nur ein lvalue-Ausdruck zugreifen, der einen der folgenden Typen aufweist:
  - ein Typ, der mit dem effektiven Objekttyp kompatibel ist,
  - eine quali fi zierte Version eines Typs, der mit dem effektiven Objekttyp kompatibel ist,
  - ein Typ, bei dem es sich um den Typ mit oder ohne Vorzeichen handelt, der dem effektiven Typ des Typs entspricht   Objekt,
  - ein Typ, bei dem es sich um den Typ mit oder ohne Vorzeichen handelt, der einer quali fi zierten Version von   effektive Art des Objekts,
  - Ein Aggregat- oder Unionstyp, der einen der oben genannten Typen enthält   Mitglieder (einschließlich, rekursiv, ein Mitglied eines Unteraggregats oder enthaltenen Union) oder
  - ein Zeichentyp.

Dies führt zu einem undefinierten Verhalten, so dass alles passieren kann.

  

C11 (n1570), § 4. Konformität
  Wenn eine Anforderung, die außerhalb einer Integritäts- oder Laufzeitbedingung auftritt, verletzt wird, ist das Verhalten nicht definiert.

    
md5 25.12.2012 16:53
quelle
6
%Vor%

Der Ausdruck * in dieser Anweisung ruft ein nicht definiertes Verhalten auf: Er verstößt gegen Aliasing-Regeln und kann einen nicht ausgerichteten Zugriff ausführen.

    
ouah 25.12.2012 16:53
quelle
6

Wegen +1 machen Sie einen nicht ausgerichteten Zugriff auf einen 32-Bit-Wert, d. h. die Adresse ist kein Vielfaches von vier.

x86 funktioniert unabhängig von der Ausrichtung, weil seine Wurzeln den ganzen Weg zurück zu 8-Bit-Maschinen gehen (vielleicht ist die Leistung etwas schlechter).

ARM erfordert eine Ausrichtung (wie viele andere Prozessoren), daher sollten 32-Bit-Werte an Adressen platziert werden, die ein Vielfaches von vier Bytes sind. Wenn dies nicht der Fall ist, können verschiedene schlimme Dinge passieren (falsche Werte, Fehler). Für das Array kümmert sich der Compiler darum, aber wenn Sie den Zeiger explizit umsetzen, erzwingen Sie, dass er die Ausrichtung verletzt.

    
starblue 25.12.2012 21:34
quelle
2

BEARBEITEN: Bitte beachten Sie, dass der Hauptteil dieser Antwort durch die Kommentare, die dazu aufgefordert werden, irrelevant wird.

Die Theorie der anderen Antworten ist in Ordnung, hilft dir aber wahrscheinlich nicht. Das eigentliche Problem ist, dass Sie geschrieben haben:

%Vor%

Wenn Sie etwas wie

geschrieben haben sollten %Vor%

, weil Sie den Zeiger als Zeiger auf einen geeigneten Typ erhöhen müssen (damit die Inkrementierungsoperation die Größe eines Elements hinzufügt), bevor Sie ihn auf etwas anderes anwenden.

Aber man könnte fragen, ob Sie wirklich einen Bytezeiger auf einen 32-Bit-Wert haben wollen. Vielleicht beabsichtigen Sie, darauf byteweise zuzugreifen (achten Sie darauf, dass die Byte-Reihenfolge zwischen den Systemen variiert!). Oder vielleicht wollten Sie wirklich, dass der Punkt ein Zeiger auf einen 32-Bit-Wert ist, der wiederum an anderer Stelle ein Zeiger auf einen 8-Bit-Wert ist ...

    
Chris Stratton 25.12.2012 20:59
quelle

Tags und Links