Forum: Mikrocontroller und Digitale Elektronik Google Test mit -fshort-enums --> Segmentation fault


von Bitschubser (Gast)


Lesenswert?

Eine C-Firmware, die ich mit dem Unit-Testframework "Google Test" testen 
muss, wird mit der Compileroption "-fshort-enums" übersetzt. Enums 
werden auch in Strukturen benutzt. Es ist wichtig, dass die Strukturen 
die selbe Größe wie in der originalen Firmware besitzen. Die Firmware 
wird mit dem AVR-GCC und das Testprogramm mit dem MINGW compiliert. Das 
Testprogramm soll auf dem PC laufen.

Benutze ich "-fshort-enums" um das Testprogramm zu übersetzen, stürzt 
das Programm mit einem Segmentation Fault ab. Das passiert beim 
Verlassen eines Testfalls, der eine C-Funktion testet, in der ein Enum 
benutzt wird. Entferne ich die Compileroption, tritt der "Segmentation 
Fault" nicht mehr auf. Allerdings schlagen dann die Testfälle fehl.

Die Option nur für das C-File zu benutzten ist leider nicht möglich. 
Denn es gibt globale Variablen und Funktionsparameter (zu testende 
Funktionen und Mocks) die entsprechende Strukturen benutzen, und diese 
müssen aus dem C++ Testprogramm heraus ebenfalls benutzt werden.

Meine Suche im Internet nach diesem Problem hat leider kein Ergebnis 
zutage gefördert. Hat jemand eine Idee, wie man diesen Widerspruch lösen 
kann? Gibt es relevante Optionen mit dem man das Google Test steuern 
kann? Oder muss man das Google Test selbst mit dieser Option übersetzen?

von Cer (Gast)


Lesenswert?

hast du dir schon die alignment optionen für structs angeschaut?

von Bernd K. (prof7bit)


Lesenswert?

Hast Du alle Bestandteile von "Google Test" ebenfalls mit -fshort-enums 
kompiliert?

Vielleicht hilft es auch einfach nur das besagte Enum mit dem Attribute 
_packed_ zu belegen und die Compileroptionen diesbezüglich komplett in 
Ruhe zu lassen, das hat den gewünschten Effekt für die Größe genau 
dieses enums und beeinflußt keinerlei anderen Sachen:
1
#define PACKED                          __attribute__ ((__packed__))
2
3
typedef enum PACKED { // sizeof == 1
4
    OT_NO_NC,
5
    OT_NC_NO,
6
    OT_NO,
7
    OT_NC
8
} settings_outtype_t;

von Bitschubser (Gast)


Lesenswert?

Vielen Dank für Eure Antworten.

Bernds Antwort war die Lösung:

#define PACKED                          _attribute_ ((_packed_))

typedef enum PACKED { // sizeof == 1
    OT_NO_NC,
    OT_NC_NO,
    OT_NO,
    OT_NC
} settings_outtype_t;

Mir war nicht bewusst, daß man das Attribut _packed_ auch bei Enums 
benutzen kann.

@Cer
Entsprechend Bernds Vorschlag, wird dieses Attribut auch für die 
Strukturen angewendet. Ansonsten werden außerdem die folgenden Optionen 
benutzt:

-mno-ms-bitfields -Wno-packed-bitfield-compat

von Bernd K. (prof7bit)


Lesenswert?

Bitschubser schrieb:
> Entsprechend Bernds Vorschlag, wird dieses Attribut auch für die
> Strukturen angewendet.

Das würd ich nicht machen, stattdessen würde ich (wenn es nicht schon zu 
spät ist) die Elemente so anordnen daß gemäß self-alignment Regeln gar 
kein Padding entstehen kann! (Vgl. ESR: "Lost Art of Structure 
Packing") Somit hast Du sowohl platzmäßig das selbe Ergebnis wie packed 
und zusätzlich noch die Gewissheit daß der Compiler dennoch keine 
Verrenkungen im Code erzeugen muß um auf krumm verschobene Datenworte 
zuzugreifen weil alles trotz dichtestmöglicher Packung immer noch sauber 
aligned ist.

von Oliver S. (oliverso)


Lesenswert?

Nur eine Frage am Rande:

Das int beim avr-gcc 16 Bit, im PC-Tetsprogramm aber 32 Bit hat, spielt 
keine Rolle bei den Tests?

Oliver

von Bitschubser (Gast)


Lesenswert?

@Bernd
Das ist mir schon klar, daß das die ideale Lösung wäre. Leider ist das 
eine große Firmware und ich bin lediglich der Tester. Mal sehen ob sich 
die Programmierer überzeugen lassen. :-)

@Oliver
Es werden die Datentypen aus der std_int.h benutzt. Also z.B.: int32_t

Nochmals vielen Dank!

von Bernd K. (prof7bit)


Lesenswert?

Oliver S. schrieb:
> Das int beim avr-gcc 16 Bit, im PC-Tetsprogramm aber 32 Bit hat, spielt
> keine Rolle bei den Tests?

Wenn er vorausschauend ist (was ich vermute wenn er sich schon Gedanken 
über Enum-Größen macht und diese erzwingen will) benutzt er keine 
solchen Gummidatentypen wie int in binären Interfaces zur Außenwelt 
sondern nagelt dort alles aufs Bit genau fest und dokumentiert das.

von Theor (Gast)


Lesenswert?

Nur mal so aus Interesse.

Ein bisschen verwirrt mich diese Lösung. Allerdings habe ich noch nie 
mit Google Test gearbeitet.

Ich vermute, dass Google Test zusammen mit dem Anwendungscode compiliert 
und zu einem Objekt gelinkt wird. Richtig?

An sich sollte doch -fshort_enums alle enum-Grössen minimieren (sofern 
es bei allen Compileraufrufen verwendet wird).

D.h. wird Google Test zusammen mit dem AVR-Code mit MinGW compiliert, 
dann sollte -fshort_enums sowohl die enums im AVR-Code als auch die in 
Google Test beeinflussen. Richtig?

Warum wirkt dann das Attribut, aber nicht -fshort_enums?

von Bitschubser (Gast)


Lesenswert?

@Theor
Ich habe die Entwicklungsumgebung inclusive dem Google Test von einem 
Kollegen bekommen. Das Google Test war bereits als Libraries compiliert, 
die ich nur hinzu linke.

von Bernd K. (prof7bit)


Lesenswert?

Theor schrieb:
> Ich vermute, dass Google Test zusammen mit dem Anwendungscode compiliert
> und zu einem Objekt gelinkt wird. Richtig?
>
> An sich sollte doch -fshort_enums alle enum-Grössen minimieren (sofern
> es bei allen Compileraufrufen verwendet wird).

Spekulation: Vielleicht benutzt das irgendwelche unter-makefiles die ein 
Eigenleben haben und eigene Optionen setzen oder die man separat noch 
irgendwie konfigurieren müsste um da was zu ändern.

von Bitschubser (Gast)


Lesenswert?

Damit meinte ich das Google Test selbst. Das Testprogramm mit den 
Testfällen wird natürlich mit dem zu testenden C-File zusammen 
kompiliert.

von Theor (Gast)


Lesenswert?

Bitschubser schrieb:
> @Theor
> Ich habe die Entwicklungsumgebung inclusive dem Google Test von einem
> Kollegen bekommen. Das Google Test war bereits als Libraries compiliert,
> die ich nur hinzu linke.

Ah. Verstehe.

Irgendwie hat mich dieser Satz:

Bitschubser schrieb:
> [,,,] Oder muss man das Google Test selbst mit dieser Option übersetzen?

angezupft.

D.h. also:

1. Google Test Infrastruktur ist vermutlich ohne -fshort_enum 
übersetzt. Ergibt eine Lib oder ein Object-File, das gelinkt wird. (Ich 
vermute, dass die Infrastruktur selbst garnicht auf die Daten der 
Anwendung zugreift).

2. Das Testprogramm ist sowohl mit als auch ohne -fshort_enum übersetzt 
worden.

3. Das Anwendungsprogramm (der AVR-Code) ist sowohl mit als auch ohne 
-fshort_enum übersetzt worden.

4. Alle vier möglichen Kombinationen von Punkt 2. und 3. ergeben einen 
Segmentation-Fault.

5. ABER: attribute packed angewendet auf eine bestimmte Struktur 
beseitigt den Fehler.

Hm. Das scheint mir auffällig widersprüchlich und klärungsbedürftig. 
Aber das sind nur meine 5 Cents.

von Bernd K. (prof7bit)


Lesenswert?

Bitschubser schrieb:
> Damit meinte ich das Google Test selbst. Das Testprogramm mit den
> Testfällen wird natürlich mit dem zu testenden C-File zusammen
> kompiliert.

Naja, dann ist es kein Wunder. Wenn Du eine Compileroption setzt die die 
Macht hat das ABI zu ändern dann kannst Du die nicht mehr mit 
vorkompilierten Libs zusammenlinken die ohne diese Option kompiliert 
wurden.

Ich hab früher auch -fshort-enums verwendet für den selben Zweck wie Du, 
bin aber wieder davon abgekommen mit derart schweren Geschützen mit so 
einer Reichweite und Zerstörungskraft zu schießen nur um an 2 oder 3 
kleinen Stellen was zu erzwingen. Da es ab dem Moment eh 
compilerabhängig wird kann ich von 2 Möglichkeiten auch diejenige nehmen 
die gezielter wirkt und weniger breit einschlägt.

Was ich außerdem noch immer mache an solchen Stellen ist mit 
_Static_assert() zur Kompilezeit das sizeof() der betreffenden structs 
zu prüfen um sicherzugehen daß da in der Zukunft absolut nichts mehr 
unbemerkt verrutschen kann ohne daß sofort die Alarmglocken losgehen 
weil es sich dann weigern wird zu kompilierten.

von Theor (Gast)


Lesenswert?

Bernd K. schrieb:
> Bitschubser schrieb:
>> [...]
>
> [...] Wenn Du eine Compileroption setzt die die
> Macht hat das ABI zu ändern dann kannst Du die nicht mehr mit
> vorkompilierten Libs zusammenlinken die ohne diese Option kompiliert
> wurden.
>
> [...]

Sehe ich ähnlich. Die tatsächlichen Auswirkungen wg. der ABI sollte man 
mal untersuchen.

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.