Frage

Ich porte eine Anwendung auf eine ARM -Plattform in C, die Anwendung wird auch auf einem X86 -Prozessor ausgeführt und muss rückwärts kompatibel sein.

Ich habe jetzt einige Probleme mit variabler Ausrichtung. Ich habe das GCC -Handbuch für gelesen__attribute__((aligned(4),packed)) Ich interpretiere, was gesagt wird, wenn der Beginn der Struktur auf die 4 -Byte -Boundry ausgerichtet ist und die Innenseite aufgrund der verpackten Aussage unberührt bleibt.

Ursprünglich hatte ich das, aber gelegentlich wird es nicht mit der 4 -Byte -Grenze aufgeteilt.

typedef struct  
{  
 unsigned int code;  
 unsigned int length;  
 unsigned int seq;  
 unsigned int request;  
 unsigned char nonce[16];  
 unsigned short  crc;  
} __attribute__((packed)) CHALLENGE;

Also ändere ich es dazu.

typedef struct  
{  
 unsigned int code;  
 unsigned int length;  
 unsigned int seq;  
 unsigned int request;  
 unsigned char nonce[16];  
 unsigned short  crc;  
} __attribute__((aligned(4),packed)) CHALLENGE;

Das Verständnis, das ich zuvor erklärte, scheint falsch zu sein, da beide Strukturen jetzt an einer 4 -Byte -Grenze ausgerichtet sind, und die Insider -Daten sind nun an einer vier Bytegrenze ausgerichtet Größe von 42 bis 44 Bytes. Diese Größe ist kritisch, da wir andere Anwendungen haben, die davon abhängen, dass die Strukturen 42 Bytes sind.

Könnte mir einige beschreiben, wie ich die von mir benötigte Operation ausführen kann? Jede Hilfe wird sehr geschätzt.

War es hilfreich?

Lösung

Wenn Sie abhängig sind sizeof(yourstruct) Da Sie 42 Bytes sind, werden Sie von einer Welt nicht portierbarer Annahmen gebissen. Sie haben nicht gesagt, wofür dies ist, aber es ist wahrscheinlich, dass die Endiantheit des Strukturinhalts auch wichtig ist, sodass Sie dort auch eine Missvereinbarung mit dem X86 haben.

In dieser Situation denke ich, dass die einzige sichere Art zu tun ist, sie zu benutzen unsigned char[42] in den Teilen, an denen es wichtig ist. Schreiben Sie zunächst eine genaue Spezifikation von genau, in welchen Feldern in diesem 42-Byte-Block und in welchen Endian diese Definition in diesem 42-Byte-Block befinden, um einen Code zu schreiben, um zwischen dieser und einer Struktur zu übersetzen, mit der Sie interagieren können. Der Code wird wahrscheinlich entweder ein Serialisierungscode (auch bekannt als Marshalling) oder eine Reihe von Gettern und Setter sein.

Andere Tipps

Dies ist ein Grund, warum das Lesen von ganzen Strukturen statt mit Mitgliedern fehlschlägt und vermieden werden sollte.

In diesem Fall bedeutet das Verpacken und Ausrichten von 4 auf 4 zwei Bytes von Polsterung. Dies geschieht, weil die Größe kompatibel sein muss, um den Typ in einem Array zu speichern, wobei alle Elemente, die noch bei 4 ausgerichtet sind.

Ich stelle mir vor, Sie haben so etwas wie:

read(fd, &obj, sizeof obj)

Da Sie diese 2 Polsterbytes, die zu verschiedenen Daten gehören, nicht lesen möchten, müssen Sie die Größe explizit angeben:

read(fd, &obj, 42)

Was Sie aufrechterhalten können:

typedef struct {
  //...
  enum { read_size = 42 };
} __attribute__((aligned(4),packed)) CHALLENGE;

// ...

read(fd, &obj, obj.read_size)

Oder wenn Sie keine Funktionen von C ++ in Ihrem C verwenden können:

typedef struct {
  //...
} __attribute__((aligned(4),packed)) CHALLENGE;
enum { CHALLENGE_read_size = 42 };

// ...

read(fd, &obj, CHALLENGE_read_size)

Bei der nächsten Refactoring -Gelegenheit würde ich dringend empfehlen, jedes Mitglied einzeln zu lesen, was in einer Funktion leicht verkapselt werden kann.

Was ist dein wahres Ziel?

Wenn es sich um Daten handelt, die sich in einer Datei oder auf dem Kabel in einem bestimmten Format befinden, sollten Sie einige Marschall-/Serialisierungsroutinen aufschreiben Programm und ein Char -Array, das sich darum befasst, wie die Daten auf der Kabel/Datei aussehen.

Dann müssen nur sorgfältig und möglicherweise plattformspezifische Code behandelt werden, die Marschallroutinen. Und Sie können einige Nice-Nasty-Unit-Tests schreiben, um sicherzustellen, dass die Marshaled-Daten ordnungsgemäß an und von der Struktur gelangen, unabhängig davon, welche Plattform Sie heute und in Zukunft portieren müssen.

Ich habe Strukturen von Linux, Windows, Mac, C, Swift, Montage usw. hin und her bewegt.

Das Problem ist nicht, dass es nicht getan werden kann, das Problem ist, dass Sie nicht faul sein können und Ihre Werkzeuge verstehen müssen.

Ich verstehe nicht, warum Sie nicht verwenden können:

typedef struct  
{  
 unsigned int code;  
 unsigned int length;  
 unsigned int seq;  
 unsigned int request;  
 unsigned char nonce[16];  
 unsigned short  crc;  
} __attribute__((packed)) CHALLENGE;

Du kann Verwenden Sie es und es erfordert keinen speziellen oder cleveren Code. Ich schreibe viel Code, der sich mit dem Arm vermittelt. Strukturen lassen die Dinge funktionieren. __attribute__ ((packed)) ist mein Freund.

Die Wahrscheinlichkeit, in einer "Welt des Schadens" zu sein, sind Null, wenn Sie verstehen, was mit beiden los ist.

Schließlich kann ich nicht für das Leben erkennen, wie Sie 42 oder 44 erhalten. Int ist entweder 4 unsere 8 Bytes (abhängig vom Compiler). Damit wird die Zahl entweder 16+16+2 = 34 oder 32+16+2 = 50 - unter der Annahme, dass sie wirklich verpackt ist, eingesetzt.

Wie ich schon sagt, ist es Teil Ihres Problems, Ihre Werkzeuge zu kennen.

Ich würde vermuten, dass das Problem darin besteht sizeof). Die Größe als 44 erzwingt die Ausrichtung in diesen Fällen, wie Sie es angefordert haben. Wenn der interne Versatz jedes Strukturmitglieds gleich bleibt, können Sie die 44 Bytestruktur so behandeln, als ob sie 42 Bytes wären (solange Sie darauf achten, die folgenden Daten an der richtigen Grenze auszurichten).

Ein Trick, den man ausprobieren kann, könnte sein beide von diesen Strukturen innerhalb eines einzelnen Gewerkschaftstyps und verwenden Sie nur eine 42-Byte-Version aus jeder dieser Vereinigung.

Da ich Linux benutze, habe ich das von gefunden echo 3 > /proc/cpu/alignment Es wird mich mit einer Warnung ausstellen und das Ausrichtungsproblem beheben. Dies ist eine Arbeit, aber es ist sehr hilfreich, wenn es darum geht, wo die Strukturen nicht falsch ausgerichtet sind.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top