Hallo zusammen,
nach einer Rechner-Neuinstallation hat mir Atmel-Studio den AVR-GCC
4.8.1 untergeschoben, mit dem ein Altprojekt, das mit AVR-GCC 4.7.2 noch
problemlos lief, mit dem Fehler "unrecognizable insn" den Build
abbricht.
Zurückführen konnte ich alles auf die folgende Zeile (von deren Typ es
mehrere gibt):
Ich bekomme es also bei einem Zeiger im Flash auf einen String im Flash
mit einem internen Kompilerfehler zu tun.
Ich habe das Ganze noch nicht mit neueren AVR-GCC-Versionen ausprobiert,
ob der Fehler schon gefixed ist.
Da die Version 4.8.1 mit dem Atmel Studio 6 SP2 ausgeliefert wird,
dürfte sie weit verbreitet sein. Deswegen suche ich erst einmal einen
Workaround für diese Compilerversion.
Viele Grüße
W.T.
OK, ich habe meinen Workaround gefunden. strncpy_P scheint von diesem
Compilerfehler nicht betroffen zu sein und mit dem Zwischenschritt, die
Zeichenkette erst ins SRAM zu kopieren kann ich vorerst leben, da ich
ohnehin einen Puffer für Zeichenketten vorhalten muß.
hp-freund schrieb:> Vielleicht hilft auch ein:> -fno-optimize-sibling-calls
Ich habe es gerade einmal ausprobiert: Das bewirkt keinen Unterschied in
Bezug auf den Compilerfehler.
Walter T. schrieb:> und wenn nein: Wo finde ich die Einschränkung?
In deinem Oberstübchen.
snprintf() wird den Formatstring lesen (bis zu einer abschließenden 0)
und den Zielpuffer dabei überschreiben.
Daß snprintf() dazu einen temporären Zwischenspeicher nimmt, kann man
nicht erwarten, weil ja im Voraus nicht klar ist, wie groß der sein
müsste.
Davon auszugehen, daß das funktioniert, ist etwas gleichbedeutend mit
"ja, ich will bis zum Ende meines Lebens der hier anwesenden..."
@Mod: Danke für's verschieben, hatte beim Erstellen vergessen, das
richtig zu setzen.
Klaus W. schrieb:> In deinem Oberstübchen.>> snprintf() wird den Formatstring lesen (bis zu einer abschließenden 0)> und den Zielpuffer dabei überschreiben.
Von der gleichen Funktionsweise gehe ich auch aus. Aber:
1. mein Oberstübchen sagt mir, daß Einschränkungen einer Funktion der
Standard-Library irgendwo explizit niedergeschrieben sein sollten
anstelle daß sich der Nutzer Gedanken über die interne Funktionsweise
machen sollte,
2. manche Implementierungen der vsprintf benötigen explizit malloc und
3. ich habe es gerade ausprobiert und es funktioniert (zumindest
oberflächlich)
Vielleicht ist für die Diskussion über sprintf ein eigener Thread
sinnvoll.
Falls der oben beschriebene AVR-GCC-Bug als bekannt anzunehmen ist, ist
das Threadthema, für mich allerdings erst einmal erledigt - ansonsten
würde ich mich noch hinsetzen für ein Minimalbeispiel.
Walter T. schrieb:> 1. mein Oberstübchen sagt mir, daß Einschränkungen einer Funktion der> Standard-Library irgendwo explizit niedergeschrieben sein sollten> anstelle daß sich der Nutzer Gedanken über die interne Funktionsweise> machen sollte,
Im Papier N1539 (einem Draft von C11) steht:
7.21.6.5 The snprintf function
Synopsis
#include <stdio.h>
int snprintf(char * restrict s, size_t n,
const char * restrict format, ...);
Beachte das 'restrict': es bedeutet, dass die Funktion davon ausgehen
kann, dass alle so in der Parameterliste gekennzeichneten Pointer auf
nicht-überlappende Speicher zeigen.
> 3. ich habe es gerade ausprobiert und es funktioniert (zumindest> oberflächlich)
Wenn du hinter dem %u noch was anderes dranhängst, würde ich einen Crash
erwarten.
Walter T. schrieb:> 3. ich habe es gerade ausprobiert und es funktioniert (zumindest> oberflächlich)
bei mir klappt es schon mal nicht (wenn ich anschließend den den Puffer
ausgeben, kommt nichts).
Wesentlich wahrscheinlicher geht es auch bei dir schief, wenn du nicht
%u gnädigerweise mit nur 2 Zeichen aus der 10 überschreibst, sondern mit
einer Zahl, die mehr Stellen braucht.
Daß etwas in einem Fall auf einem System funktioniert, ist kein starkes
Argument :-)
Wobei das auch mal eine interessante Technik wäre: während eines
sprintf() %-Direktiven auszugeben, die dann im weiteren Verlauf wieder
interpretiert werden.
Damit kann man bestimmt schöne Sachen bauen (wenn auch nur bedingt
portabel). Wenn auch eher als abschreckendes Beispiel...
Klaus W. schrieb:> Wobei das auch mal eine interessante Technik wäre: während eines> sprintf() %-Direktiven auszugeben, die dann im weiteren Verlauf wieder> interpretiert werden.
Der OCCC wartet :-)
tictactoe schrieb:> Beachte das 'restrict': es bedeutet, dass die Funktion davon ausgehen> kann, dass alle so in der Parameterliste gekennzeichneten Pointer auf> nicht-überlappende Speicher zeigen.
Es steht auch noch explizit drin:
tictactoe schrieb:> Im Papier N1539 (einem Draft von C11) steht:Jörg W. schrieb:> Es steht auch noch explizit drin:> If copying takes place between objects> that overlap, the behavior is undefined.
OK, damit gehört der N1570 zukünftig zu meinen Standardquellen.
Danke!
Walter T. schrieb:> Falls der oben beschriebene AVR-GCC-Bug als bekannt anzunehmen ist,
Da sowohl Testfall als auch Optionen und Fehlermeldung geheim sind:
Vielleicht ja. Vielleicht nein.
Johann L. schrieb:> Da sowohl Testfall als auch Optionen und Fehlermeldung geheim sind
Weder der Testfall noch die Fehlermeldung sind geheim. Das Projekt ist
lediglich mal wieder ein Weilchen liegengeblieben.
Im Wesentlichen sieht der Testfall so aus:
Das Ganze ist eher unübersichtlich und weit entfernt von einem
Minimalbeispiel - falls das hilfreich ist, kann ich das aber noch
nachliefern.
Mit den folgenden Build-Optionen:
avr-gcc.exe" -x c -funsigned-char -funsigned-bitfields
-DF_CPU=7372800UL -Os -ffunction-sections -fdata-sections -fpack-struct
-fshort-enums -Wall -Wextra -Wundef -pedantic -mmcu=atmega32 -c
-gdwarf-2 -std=gnu99 -fwrapv -H -Wsign-conversion -v -MD -MP -MF
"common/src_menu/menu.d" -MT"common/src_menu/menu.d"
-MT"common/src_menu/menu.o" -o "common/src_menu/menu.o"
"../common/src_menu/menu.c"
Using built-in specs.
sieht die Konsolen-Ausgabe wie folgt aus:
1
C:\Users\Nicolas\Desktop\SVN\2015_Rotorsteuerung\Firmware_AVR\Pulsgenerator04\common\src_menu\menu.c(177,6): warning: #warning is a GCC extension [enabled by default]
2
#warning "GCC 4.8.1 needs workaround for flash strings"
Vermutlich
https://gcc.gnu.org/PR61443
...aber nur geraten, weil das Beispiel sich nicht compilieren lässt. Du
hast wohl nie versucht, den angeblichen Testfall zu übersetzen :-/
Walter T. schrieb:> Das Ganze ist eher unübersichtlich und weit entfernt von einem> Minimalbeispiel - falls das hilfreich ist, kann ich das aber noch> nachliefern.
Ein Minimalbeispiel ist immer hilfreich.
Die wenigsten Fehler sind so, dass man sie nur durch hinsehen sofort
weiß, was Sache ist.
Dir ist schon aufgefallen, dass in der geposteten Funktion die
Block-Klammerung nicht stimmt? Da ist eine } zu viel.
Ob das was damit zu tun hat?
Keine Ahnung. Vielleicht ist das ja auch nicht der komplette
Original-Code.
Hallo zusammen,
ich habe mal ein "nicht-ganz-Minimalbeispiel" gemacht. In Atmel-Studio
6.2 sollte es direkt build-bar sein und mit dem ein- und auskommentieren
der Zeile 61 in main.c ist der Fehler erzeugbar.
Ich habe kein noch kleineres Minimalbeispiel erstellt, weil ich sonst
befürchten muß, daß
a) ich aus dem ursprünglichen Fehler in einen ganz anderen laufe
(Flüchtigkeitsfehler bei der Minimierung) und
b) ansonsten die unweigerliche Frage kommt (nicht unbedingt von
bisherigen Thread-Teilnehmern), warum ich solche Konstruktionen mit
struct arrays im Flash mit Zeigern auf char arrays im Flash überhaupt
nutzen will
c) ich immer noch nicht 100% ausschließen kann, daß bei mir noch ein
Programmierfehler liegt.
Walter T. schrieb:> c) ich immer noch nicht 100% ausschließen kann, daß bei mir noch ein> Programmierfehler liegt.
Da kann ich dich beruhigen.
Wenn der Compiler abkratzt, dann ist das ein Fehler im Compiler.
Egal was du schreibst, und sei es der größte Unsinn, der Compiler darf
nicht abschmieren.
Hallo Karl-Heinz,
wenn wir ehrlich sind, kratzt der Compiler nicht ab, sondern stellt
seine Tätigkeit mit einer mehr oder weniger definierten Fehlermeldung
ein. Nicht auf optimale Weise, aber immerhin muß das Betriebssystem
nicht hinterher die Scherben wegkehren.
Kann bitte einer der C-Experten prüfen, ob er das aufgrund eigentlich
korrekten Codes macht (womit es ein echter Compilerfehler ist) oder nur
die anderen Compilerversionen so großzügig sind, das erwartete Verhalten
bei ungültigem Code zu liefern (womit es nur ein ungünstiges
Compilerverhalten, aber kein Fehler ist).
Ich habe mir die Sachen jetzt leider schon so oft angesehen, daß ich
einen Fehler noch nicht einmal mehr dann sehen würde, wenn er rot
blinkte.
Viele Grüße
W.T.
Eine unrecognizable INSN ist immer ein „echter Compilerfehler“.
Johann hatte ja weiter oben bereits eine Vermutung geäußert, um welchen
Bug es sich handelt. Ich würde diese Vermutung bestätigen: wenn du in
der Funktion, bei der der Fehler auftritt, den Aufruf nach snprintf
auskommentierst, dann compiliert er durch.
Jörg W. schrieb:> Johann hatte ja weiter oben bereits eine Vermutung geäußert, um welchen> Bug es sich handelt. Ich würde diese Vermutung bestätigen
OK, wenn ihr beiden sagt, daß es ein bekannter Bug ist, dann gehe ich
mal davon aus, das das stimmt. Das spart mir auch den Gegentest mit dem
AVR-GCC 4.9.1 oder 4.8.4, falls am Wochenende das Wetter schlecht genug
ist.
Für mich ist die Sache damit erledigt - es sei denn, einem geneigten
Mitleser fällt noch ein besserer Workaround als das Kopieren des
gesamten Strings ein.
Walter T. schrieb:> es sei denn, einem geneigten Mitleser fällt noch ein besserer Workaround> als das Kopieren des gesamten Strings ein.
Benutzung von GCC 4.8.4 oder 4.9.1, für beide nennt der Bugreport die
Sache als erledigt. Johann hat den Fix auf beide Branches zurück
portiert.
Jörg W. schrieb:> Benutzung von GCC 4.8.4 oder 4.9.1
Du beschreibst hier eine sinnvolle Lösung, keinen Workaround :-)
Solange die Atmel-Toolchain noch auf den AVG-GCC 4.8.1 setzt, werde ich
aber wohl oder übel noch diese Version unterstützen müssen.
Wobei der Grund dazu aber schon Off-Topic ist: Ich bin der Meinung, wenn
ich meine Projekte (als abschreckendes Beispiel) Open Source mache,
sollte ich nicht auf irgendwelche aufwendig installierbare
Build-Umgebungen setzen. Und die Atmel-Toolchain ist noch auf AVR-GCC
4.8.1, WinAVR auf 4.3.3.