Fehlermeldung "must be const in order to be put into read-only section.."

OP (Firma: keine) #2839005
Lesenswert?

Hallo,

folgendes Problem.
Ich habe ein sehr umfangreiches programm für einen mobilen Roboter 
geschrieben.
µC: ATXMega128A1
Bisher habe ich alles mit WinAVR erstellt.
Allerdings habe ich seit kurzem das Problem das der Controller sich 
festsetzt. Meine Vermutung es liegt an einem Buffer overflow oder einem 
Stack overflow es könnte allerdings auch mit der String verarbeitung zu 
tun haben da ich u.a. RFID Tags (via USART) auslese.

Da ich weder eine Warnung noch eine Fehlermedlung beim compilieren 
erhalte kam ich auf die Idee das Programm mit AVRStudio 6 zu 
compilieren.
Allerdings erhalte ich dort folgende Fehlermeldung.

Error  1  variable 'DeutschHead' must be const in order to be put into 
read-only section by means of '__attribute__((progmem))
für folgende Zeile
const char *DeutschHead[] PROGMEM = {
  TextDEHEAD1,
  TextDEHEAD2,
  TextDEHEAD3,
};

Wegen dieser Fehlermeldung wird das Programm nicht kompiliert.

Hat jemand einen tipp ?

Oder vielleicht noch eine Herangehensweise wie ich mein Programm 
überprüfen kann.

MfG

Andreas
OP (Firma: keine) #2839062
Lesenswert?

Hallo,

ja schöner Deutsch !! Denglisch halt, passiert mir täglich.
Die Änderung führte zu zwei neuen Fehlermeldungen.

Error  1  expected '=', ',', ';', 'asm' or '__attribute__' before 
'const'
Für die Zeile:
const char *DeutschHead[] const PROGMEM = {

und
DeutschHead undeclared (first use in this function)
Für die Zeile:
adressehead = (const char* )(pgm_read_word( & ( DeutschHead[0] ) ) );



Wie schonn erwaehnt hat das ganze mit WinAVR keinen Fehler ausgegeben.

Hier mal der Inhalt des zusammengesetzten String Arrays
const char TextDEHEAD1[] PROGMEM = "DataLog ";
const char TextDEHEAD2[] PROGMEM = ",....";
const char TextDEHEAD3[] PROGMEM = ",....\n";

const char *DeutschHead[] const PROGMEM = {
  TextDEHEAD1,
  TextDEHEAD2,
  TextDEHEAD3,
};
Moderator Persönliche Seite #2839067
Lesenswert?

Andreas S. schrieb:

> Die Änderung führte zu zwei neuen Fehlermeldungen.

Schieb mal das const noch.  Möglicherweise muss es zwischen dem
Stern und "DeutschHead" stehen.  (Ich kann's gerade nicht recht
probieren und bin mir bei solchen Deklarationen nicht so sicher.
Andere Leute wir Karl-Heinz sind da besser als ich. ;-)

> Wie schonn erwaehnt hat das ganze mit WinAVR keinen Fehler ausgegeben.

Ja.  Der Compiler da hatte einen Bug und hat nicht auf der Konstantheit
der Flash-Objekte bestanden.

> Hier mal der Inhalt des zusammengesetzten String Arrays

Ist völlig schnuppe, das ist mit dem ersten "const" schon gut
abgedeckt.  Es muss aber noch ein zweites mit rein in die
Deklaration.
OP (Firma: keine) #2839109
Lesenswert?

Hi,

ja du hast recht !!
Damit wäre das gelöst !! Vielen dank schon mal dafür.

Das fuehrte mich auch direkt zur nächsten Fehlermeldung.
Undefinded reference ...

Ich habe mein programm mit AVRStudio 6 importiert.
Wo kann ich denn jetzt nachsehen welche .c Dateien alle mit eingebunden 
sind?

Das stand zuvor alles im Makefile.
Moderator Persönliche Seite #2839225
Lesenswert?

Andreas S. schrieb:
> Wo kann ich denn jetzt nachsehen welche .c Dateien alle mit eingebunden
> sind?

Frag' mich was leichteres, ich benutze kein Atmel Studio (schon
deshalb nicht, weil Atmel gar nicht will, dass ich es benutze, indem
sie sich entschieden haben, es ausdrücklich nur für Windows zu
bauen ;-).

Im Zweifelsfalle lieber unter "PC Hard- und Software" fragen, mit dem
GCC selbst hat das ja nicht viel zu tun, und möglicherweise lesen dort
mehr/andere Leute mit, die die Frage beantworten können.
OP (Firma: keine) #2839888
Lesenswert?

Vielen Dank für Eure schnelle und kompetente Hilfe,

hinzugefügt hatte ich die .c files schon allerdings musste bei build 
Action noch compile auswählen.

Jetzt habe ich mein programm mit AVRStudio 6 compiliert habe aber leider 
immer noch den gleichen Fehler. :-(
Ich werd jetzt mal einen neuen Beitrag erstellen wo es explizit um die 
neue Problemstellung geht.

Gruß Andreas
Moderator Persönliche Seite #7390495
Lesenswert?

Joachim B. schrieb:

keine Ahnung warum das immer wieder geändert werden muss

Steht oben: das alten Verhalten ("const" oder nicht interessierte den Compiler nicht) war de facto ein Bug, denn natürlich waren Flash-Objekte schon immer zwangsweise konstant *). Dein Code hätte es also auch früher schon richtig machen können und so deklarieren, statt dass du erst wartest, bis der Compiler auch drauf besteht, dass es so ist. ;-)

*) self-programming kann man in diesem Zusammenhang außen vor lassen.

Moderator Persönliche Seite #7390509
Lesenswert?

Joachim B. schrieb:

Jörg W. schrieb:

denn natürlich waren Flash-Objekte schon immer zwangsweise konstant

eben und deswegen irritiert ja das Compilerverhalten zu meckern und auf const zu bestehen.

Nein, es ist folgerichtig und hätte schon immer so sein sollen. Sonst kann er dir nicht anmosern wenn dein Code versucht, an diesen "Variablen" etwas zu ändern.

#7390572
Lesenswert?

Joachim B. schrieb:

und warum war es 2015 nicht richtig?

Ich programmiere in C seit 1988 und hoffte im 3ten Jahrtausend nicht so "fehlerhafte" Compiler zu finden.

Dein WinAVR-Compiler wurde in IT-Zeit gerechnet kurz vor dem Bau der ersten Pyramide geschaffen (gcc 3.xxx). Damals war man froh, daß es überhaupt etwas für den AVR mit seiner Harvard-Architektur gab.

Und ich wette mal, daß du damals das Wörtchen „const“ in C auch sonst noch nie benutzt hattest.

Oliver

Moderator Persönliche Seite #7390712
Lesenswert?

Joachim B. schrieb:

das sagt doch PROGMEM,

Nein, tut es aus Syntax-Sicht nicht, dafür braucht es das "const" (oder besser "constexpr" in C++ bzw. künftig in C23).

Du sollst auch bitte alles, was nicht veränderbar sein muss, in deinem C-Code als "const" deklarieren. Nur so kann der Compiler dir anmosern, wenn du dann trotzdem versuchst, es zu ändern (ggf. unbewusst, weil du einen Zeiger an eine Funktion weiterreichst, die ihrerseits versuchen könnte, da was hin zu schreiben).

um des ändern Willens

Es geht nicht "um des Änderns Willen", sondern darum, dass der vorherige Zustand unpassend war. Du bist ja das beste Beispiel dafür: du nahmst an, dass PROGMEM allein für den Compiler schon genügt um mitzuteilen, dass diese Daten nicht änderbar sind. Tatsächlich war das aber nicht der Fall, bei vorherigen Zustand hätte dir der Compiler also sowas:

1
char s[] PROGMEM = "Hi there";
2

3
// ...
4
   strcpy(s, "Hello");

durchgehen lassen, weil ihm niemand mitgeteilt hat, dass s[] gar nicht änderbar ist.

Mit dem aktuellen Compiler wirst du gezwungen, es so zu schreiben (was du natürlich früher hättest auch schon tun können und sollen):

1
const char s[] PROGMEM = "Hi there";

und der Versuch, mit strcpy() drauf zu schreiben hätte dir erzählt, dass das mit einem const-Argument so nicht geht.

#7390744
Lesenswert?

Jörg W. schrieb:

Nur, weil dir ein Compiler irgendwann mal was durchgehen lassen hat

Entwedder war der Compiler 2015 fehlerhaft oder er ist es heute, beides halte ich für unwahrscheinlich. Es nervt wenn man bei Projekten immer den alten Rechner am Leben halten muss. Ferner satnd damals das PROGMEM vorne, später vor dem =. Macht das jeder nach Lust und Laune oder würfelt es aus?

Wie soll man zu Programmierern Vertrauen haben wenn morgen ALLES anders ist?

Jörg W. schrieb:

Du bist ein Starrkopf.

ist das so oder verstehst du nicht was ich meine?

Jedenfalls danke ich für deine Hilfe und Erklärungen und muss mich nun um andere Baustellen kümmern, wie Restring am eagle, WS2812B Lib usw.

Moderator Persönliche Seite #7390786
Lesenswert?

Joachim B. schrieb:

Entwedder war der Compiler 2015 fehlerhaft oder er ist es heute, beides halte ich für unwahrscheinlich.

Es ist ja nicht ernsthaft ein Fehler (weil er damit nichts wirklich falsch macht), aber ja, man kann es damals als Fehler ansehen, dass er nicht auf "const" bestanden hat.

Es nervt wenn man bei Projekten immer den alten Rechner am Leben halten muss.

Musst du nicht, du kannst auch den uralten Compiler auf einem aktuellen System compilieren und installieren – aber ich würde das nicht tun.

Kommerziell wird das teilweise aber tatsächlich so gemacht, dass man die komplette alten Entwicklungsumgebung für solche Projekte vorhält. Bietet sich heutzutage natürlich an, sie dafür in einer VM "einzufrieren".

Ferner satnd damals das PROGMEM vorne, später vor dem =.

Eigentlich gehörte es schon immer hinten hin.

#7390808
Lesenswert?

Joachim B. schrieb:

keine Ahnung warum das immer wieder geändert werden muss

Das hat sich genau ein einziges Mal geändert. Hör auf, hier rumzunölen, und schreib die paar fehlenden consts da rein, und fertig.

Die AVR-Architektur ist halt etwas, was der gcc so gar nicht unterstützt. Die ganze Daten-im-Flash-Funktionalität wurde damals da mehr oder weniger elegant drangedengelt. Irgendwann später wurden dann die dabei zunächst übersehenen Ungereimtheiten glattgezogen.

Oliver

#7390905
Lesenswert?

Oliver S. schrieb:

Das hat sich genau ein einziges Mal geändert. Hör auf, hier rumzunölen,

OK

Oliver S. schrieb:

schreib die paar fehlenden consts da rein, und fertig.

done!

Oliver S. schrieb:

Die ganze Daten-im-Flash-Funktionalität wurde damals da mehr oder weniger elegant drangedengelt.

und ich versuche dazuzulernen in dem ich von "Profis" abschreibe (sprich deren LIBs nutze), die Code veröffentlichten, was offensichtlich Jahre später nicht richtig war wenn dieser Code zu neuen Fehlern führt.

Egal ihr habt es erklärt, danke.

#7390915
Lesenswert?

Als Nachtrag noch der Hinweis, daß im Zuge der "Aufarbeitung" im avr-gcc der Qualifier __flash dazugekommen ist.

Wenn dich diese Neuheit nicht völlig überfordert, kannst du dir den ja auch mal anschauen. Das ist jetzt nicht unbedingt etwas, was man in uralten Projekten aus der WinAVR-Zeit einführe möchte, aber für neue vielleicht eine Überlegung wert.

Oliver

#7390972
Lesenswert?

Sollte man das const nicht anders "verkaufen"? Man möchte const gerne freiwillig dazu schreiben, weil jede Warnung hilft! Selbst wenn man meint, dass const und PROGMEM ganz verschiedene Dinge sind.

Außerdem, was würde ohne const beim strcpy(s, "hallo") passieren? Im strcpy passieren zur Laufzeit seltsame Dinge, aber /kann/ der Compiler z.B. s[2] = ',' überhaupt übersetzen (mangels Maschinenbefehlen)?

Auf Rechnern ohne PROGMEM passiert etwas ähnliches mit Stringkonstanten. Zwei gleiche Strings werden nur einmal im RAM gespeichert. Das strcpy würde anstandslos funktionieren, die Wirkung merkt erst der Enduser ;)

Moderator Persönliche Seite #7390983
Lesenswert?

Bauform B. schrieb:

Man möchte const gerne freiwillig dazu schreiben, weil jede Warnung hilft!

Das hatte ich Joachim versucht zu verklickern. Ich weiß nur nicht, ob's bei ihm angekommen ist.

Außerdem, was würde ohne const beim strcpy(s, "hallo") passieren?

Da strcpy vom Flash nichts weiß, würde es vermutlich damit enden, dass es die übergebenen Flash-Adressen als RAM-Adressen benutzt und dann dahin schreibt.

#7391040
Lesenswert?

Jörg W. schrieb:

Bauform B. schrieb:

Man möchte const gerne freiwillig dazu schreiben, weil jede Warnung hilft!

Das hatte ich Joachim versucht zu verklickern. Ich weiß nur nicht, ob's bei ihm angekommen ist.

ich glaube hier gibt es Mißverständnisse, das "const" war nicht freiwillig, der neue GCC zwang mich mit Fehler "must be const" Es kam keine Warnung sondern es wurde abgebrochen, mag sein das diese "Voreinstellung" sinnvoll ist.

Wenn es nur eine Warnung wäre hätte es ja kompilieren können. (schliesslich läuft das Original seit 2015, da hatte auch NIEMAND die Absicht Programm Konstanten im flash zu ändern, ich weiss doch was Konstante sind.

z.B. // const char string_0[] PROGMEM = "String 0"; // "String 0" etc are strings to store - change to suit. const char mo0[] PROGMEM = " "; const char mo1[] PROGMEM = "Jan"; const char mo2[] PROGMEM = "Feb"; const char mo3[] PROGMEM = "Mar"; const char mo4[] PROGMEM = "Apr"; const char mo5[] PROGMEM = "May"; const char mo6[] PROGMEM = "Jun"; const char mo7[] PROGMEM = "Jul"; const char mo8[] PROGMEM = "Aug"; const char mo9[] PROGMEM = "Sep"; const char mo10[] PROGMEM = "Oct"; const char mo11[] PROGMEM = "Nov"; const char mo12[] PROGMEM = "Dec";

schon geändert PROGMEM vor dem =

noch original nicht geändert; const uint8_t PROGMEM BITNO[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // minute 0xFF, // parity 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, // hour 0xFF, // parity 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, // day 0x30, 0x31, 0x32, // weekday 0x40, 0x41, 0x42, 0x43, 0x44, // month 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, // year 0xFF }; // parity

const uint8_t PROGMEM BMASK[] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };

#7391686
Lesenswert?

Joachim B. schrieb:

Jörg W. schrieb:

das "const" war nicht freiwillig

Du hättest es aber freiwillig bereits zuvor benutzen können und sollen.

seit wann sind Programierer fleissig, es wird nur getippt was man unbedingt muss, also war das const damals entbehrlich und wurde logisch nicht getippt.

"const", also die read-only Qualifizierung ist ungemein wichtig, dass sollte auch ein Hobby-Programmierer wissen.

Natürlich kann man darüber streiten, ob C und C++ die defaults richtig gewählt hat, d.h. es wäre besser, dass alle Objekte zunächst read-only sind, es sei denn, man qualifiziert sie als read-write, ... (in C++ gibt es noch mehr, worüber man sich aufregen kann). Doch die Sprachen sind nun man so, wie sie sind.

#7391687
Lesenswert?

Wilhelm M. schrieb:

"const", also die read-only Qualifizierung ist ungemein wichtig, dass sollte auch ein Hobby-Programmierer wissen.

Da sag ich mal ganz vorsichtig, das sich diese Erkenntnis gerade bei C-Programmierern selbst heute noch nicht so ganz herumgesprochen hat, egal, wie professionell die auch unterwegs sind. Zu Zeiten des WinAVR war das unnötiger Hipster-Kam, auch wenn es da Hipster wohl noch gar nicht gab.

Nicht nur die Zeiten ändern sich.

Oliver

#7391691
Lesenswert?

Oliver S. schrieb:

Da sag ich mal ganz vorsichtig, das sich diese Erkenntnis gerade bei C-Programmierern selbst heute noch nicht so ganz herumgesprochen hat, egal, wie professionell die auch unterwegs sind.

Mmmh, ich weiß nicht... Sollte das in meinem Team vorkommen, so würde ich es mal mit einer (internen) "Schulung" versuchen bzw. sowas im friday-forum adressieren.

Moderator Persönliche Seite #7391725
Lesenswert?

Wilhelm M. schrieb:

Natürlich kann man darüber streiten, ob C und C++ die defaults richtig gewählt hat, d.h. es wäre besser, dass alle Objekte zunächst read-only sind, es sei denn, man qualifiziert sie als read-write

Zusammen mit by default exportierten globalen Variablen, die man erst mit "static" modulintern machen muss.

Aber klar, 50 Jahre später kann man sich vortrefflich drüber aufregen, dass die Erschaffer das vor 50 Jahren so noch nicht verstanden hatten. ;-)

#7391746
Lesenswert?

Joachim B. schrieb:

Nur, weil dir ein Compiler irgendwann mal was durchgehen lassen hat

Entwedder war der Compiler 2015 fehlerhaft oder er ist es heute, beides halte ich für unwahrscheinlich.

Das eigentliche Problem ist, dass weder die Sprache C, noch der Compiler gcc ein System hat solche Änderungen rückwärtskompatibel durchzuführen. Das liegt halt daran, dass C und mittlerweile auch gcc im Methusalemalter sind und dort halt massiv viele Dinge einfach so sind wie sie sind, weil sie schon immer so waren und nicht mehr geändert werden können.

Daraus hat man natürlich gelernt und moderne Sprachen wie Rust bieten Mechanismen (hier: Editions), mit denen solche inkompatiblen Änderungen durchgeführt werden können und gleichzeitig alter Code trotzdem weiterhin compiliert und funktioniert.

C bietet das nicht. Da bleibt nur die Möglichkeit entweder bis in alle Ewigkeit mit dem fälschlicherweise fehlenden const zu leben, oder es einmal inkompatibel zu ändern. Hier hat man sich eben dazu entschieden eine inkompatible Änderung zu machen, weil das potentiell echte Bugs aufdecken kann.

Persönliche Seite #7394392
Lesenswert?

Andreas S. schrieb:

Wie schonn erwaehnt hat das ganze mit WinAVR keinen Fehler ausgegeben.

Das neueste bzw. letzte Release von WinAVR basiert(e) auf GCC v4.3.

Offenbar bist du während des Projekts auf eine neue(re) Compilerversion umgestiegen, insbesondere Version v4.6 oder neuer.

Jährlich im Frühjahr gibt es eine neue GCC Major Release, d.h. eine Release die neue Features enthält oder welche entfernt; während die Minor Releases üblicherweise nur Probleme beheben.

Zu jeder Major-Release gibt es Release Notes, die neue, erwähnenswerte Features auflisten aber auch einen Abschnitt mit "Caveats" enthalten. Konkret für GCC v4.6 steht da:

https://gcc.gnu.org/gcc-4.6/changes.html

  • On AVR, variables with the progmem attribute to locate data in flash memory must be qualified as const.

GCC v4.6 Release war Frühjahr 2011 wenn ich mich nicht verzählt habe.

Wenn man auf eine neue GCC Version umsteigt, ist man gut damit beraten, die Release-Notes zu lesen, insbesondere die Caveats. Auch plattformspezfische Änderungen zu "AVR" können ganz interessant sein, oder zur verwendeten Sprache. So haben sich seitdem auch die default Sprachversionen von C und C++ geändert.

Dieses Frühjahr gibt es die v13, es gibt also einiges zu lesen wenn man von WinAVR umsteigt :-)

Davon ab sind nicht alle PRs (Prolbem Reports) immer gefixt; so sollte man wegen PR90706 allen avr-gcc Versionen von v9 bis einschließlich v12.2 aus dem Weg gehen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren