Forum: Mikrocontroller und Digitale Elektronik packed struct/union in C und C++


von Fabian (Gast)


Lesenswert?

Guten Abend zusammen

Ich habe einen Source Code, der in C wunderbar funktionierte und nun 
auch mit einem C++ Compiler funktionieren soll. So weit so gut... nun 
hab ich das Problem, dass bei folgender Zusweisung

curr_frame->locals[i] = vm_args[i];

im Memory fälschlicherweise jeweils 1 Byte des vorherigen class_ptr mit 
1 Byte Wert von vm_args überschrieben wird. vm_args ist natürlich 
ebenfalls vom Typ value_t. Woran könnte dies liegen?


typedef PACKED struct frame_T      frame_t;
typedef PACKED union value_T       value_t;

struct frame_T
{
    class_t     *class_ptr;
    value_t      locals[1];
};

union value_T
{
    int32   i;
    float32 f;
    uint32  val;
};

Die Struktur sowie die Union wurde mit #pragma pack(2) versehen, da 
diese typen mit dem alignment in einem file übereinstimmen müssen (und 
dies soweit auch tun). Ich benutze IAR als Compiler, die CPU ist ein 
LPC23xx von NXP.

Ich hoffe, die Angaben reichen soweit mal... Danke für eure Hilfe.

Gruss
Fabian

von ... (Gast)


Lesenswert?

ich weiß nicht wie du dir das denkst, aber bei

curr_frame->locals[i] = vm_args[i];

darf i nur 0 annehmen, alles andere bringt nicht das gewünschte 
ergebnis.

von Karl H. (kbuchegg)


Lesenswert?

1
struct frame_T
2
{
3
    class_t     *class_ptr;
4
    value_t      locals[1];
5
...

ein Array der Länge 1?
Ich wittere da einen Array-Overflow.

von ... (Gast)


Lesenswert?

ätsch :-P schneller.

von (prx) A. K. (prx)


Lesenswert?

Wozu ist hier die Packerei gut? Bei diesen Datentypen brennt auch ohne 
nichts an.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Karl Heinz Buchegger schrieb:
> ein Array der Länge 1?

Möglicherweise soll das ein "flexible array member" sein, wobei man
diese seit C99 ohne Größenangabe schreibt, also
1
struct frame_T
2
{
3
    class_t     *class_ptr;
4
    value_t      locals[];
5
};

Egal ob mit oder ohne Größenangabe, in C++ sind solche Dinge m.W.
offiziell nicht vorgesehen (höchstens vielleicht in C++11), könnten aber
trotzdem funktionieren. Ganz sicher kann man aber solche Strukturen
nicht mit new anlegen, da man dort im Gegensatz zu malloc keine
Größe übergibt, die ja in diesem Fall variabel ist.

Vielleicht liegt also der Fehler darin, dass für die Strukturen zu wenig
Speicher reserviert wird.

Welche Absicht aber tatsächlich hinter der [1] steckt, das kann uns nur
Fabian sagen.

von Fabian (Gast)


Lesenswert?

Danke für eure Antworten.

Warum die ganze packerei? Dies hat schon seinen Grund, denn der struct 
ist eigentlich deutlich grösser (dies ist nur das Ende davon...) und 
wird einerseits über bestehende Daten im Flash "gestülpt" und 
andererseits dient es zur Speicherung im RAM. Genau dort liegt das 
Problem.

Genau so ist es, wir reden hier von einem "flexible Array Member". Aber 
warum wird dieses Array nicht richtig addressiert, auch wenn ich im 
Moment nur das Element 0 benutze? Muss zwingend malloc verwendet werden? 
Wurde im C Code übrigens auch nicht...

von Udo S. (urschmitt)


Lesenswert?

Fabian schrieb:
> Die Struktur sowie die Union wurde mit #pragma pack(2) versehen, da
> diese typen mit dem alignment in einem file übereinstimmen müssen

Was soll das, mach ordentliche read und write Funktionen, dann muss gar 
nichts übereinstimmen und es ist portabel.

Fabian schrieb:
> und wird einerseits über bestehende Daten im Flash "gestülpt"

Dasselbe wie oben, das ist Trickprogrammierung. Kann man machen wenn das 
genau für eine Anwendung und einen Prozessor gemacht wird, aber beim 
Portieren immer eine Lotterie.
Wenn man hier nicht unbedingt das letzte halbe Prozent an Performance 
braucht, macht man sowas mit sauberen Konvertierfunktionen.

Meine Meinung!

von (prx) A. K. (prx)


Lesenswert?

Fabian schrieb:
> Warum die ganze packerei? Dies hat schon seinen Grund, denn der struct
> ist eigentlich deutlich grösser (dies ist nur das Ende davon...)

Ahnte ich es doch... Information hiding an entscheidender Stelle. Na 
dann such mal schön.

von Fabian (Gast)


Lesenswert?

Naja, dann poste ich das nächste mal den ganzen Source Code...
Gewisse Leute in diesem Forum werden, sofern sie nicht gerade eine 
Lösung bereit haben, seeehr schnell persönlich. Muss ich nicht haben!

Auch meine Meinung!

von Udo S. (urschmitt)


Lesenswert?

Fabian schrieb:
> Gewisse Leute in diesem Forum werden, sofern sie nicht gerade eine
> Lösung bereit haben, seeehr schnell persönlich.
??
Falls mein Beitrag gemeint sein sollte, erklärs mir.

von (prx) A. K. (prx)


Lesenswert?

Fabian schrieb:
> Naja, dann poste ich das nächste mal den ganzen Source Code...

Die ganze Struktur wär schon mal ein Ansatz. Denn in der gezeigten 
Struktur ist kein Anlass für einen einzelnen Bytezugriff zu sehen. Aber 
generell gilt es, bei Suche nach hartnäckigen Fehlern das Programm auf 
das Minimum abzuspecken, in dem das Problem immer noch auftritt. Das 
hilft nicht nur beim Posten vom Code, sondern auch dir.

Ausserdem solltest du deinen Code mal auf Stellen untersuchen, in denen 
die Adresse eines misaligned members verwendet wird, statt direkt darauf 
zuzugreifen. Ich weiss nicht wie IAR sich in diesem Fall verhält, aber 
bei GCC kann das grandios und ohne Warnung in die Hose gehen.

> seeehr schnell persönlich

Persönlich geht anders. Allerdings nervt es auf Dauer, wenn immer wieder 
Leute zielsicher genau jene Teile posten, die ziemlich wahrscheinlich 
nicht die Ursache des Problem sind (noch nerviger ist allerdings 
abgetippter Code der Marke "so ähnlich, nur ohne die ganzen Tipp- und 
Syntaxfehler").

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.