Forum: Mikrocontroller und Digitale Elektronik [rant] Schleifen ohne Seiteneffekte - Jeden Tag steht ein neuer Amateur auf :-(


von Bernd K. (prof7bit)


Lesenswert?

Man sollte meinen eine Firma wie GigaDevices könnte Leute beschäftigen 
die der Sprache C mächtig sind, zumindest in der Abteilung die den 
Demo-Code für ihre tolle Hardware fabrizieren die sie verkaufen wollen!?
1
/*!
2
    \brief      insert a delay time
3
    \param[in]  nCount: stall Count
4
    \param[out] none
5
    \retval     none
6
*/
7
void delay(uint32_t nCount)
8
{
9
    for(; nCount != 0; nCount--);
10
}

Was soll der Scheiß? Dieser Code tut nichts, der Compiler wirft also 
zurecht die ganze Funktion raus. Was erwartet der Programmierer? Daß 
der Compiler Gedanken lesen kann und verbrauchte Rechenzeit in diesem 
einen Fall plötzlich zum erwünschten Seiteneffekt wird der umgesetzt 
werden muß, aber bitteschön nur an dieser einen Stelle und an allen 
anderen Stellen soll er bitteschön weiterhin auf Zeit optimieren?

Wann hört das endlich auf, wann fangen die endlich an logisch zu denken 
und eventuell vielleicht sogar die Sprache zu lernen die sie den ganzen 
Tag lang benutzen?

: Bearbeitet durch User
von Thomas M. (langhaarrocker)


Lesenswert?

Mal eine Hypothese: n in nCount steht eigentlich für 'no'. Also gemeint 
ist 'no Count', zu Deutsch zählNix.
Aber ich bin auch auf den naheliegenden Fehlschluss hereingefallen: 
Wieso gehen wir davon aus, dass diese delay Funktion zur Laufzeit 
verzögern soll? Die ist bestimmt nur gedacht den Kompiliervorgang zu 
verlangsamen!

von Falk B. (falk)


Lesenswert?

Bernd K. schrieb:
> Man sollte meinen eine Firma wie GigaDevices könnte Leute beschäftigen
> die der Sprache C mächtig sind, zumindest in der Abteilung die den
> Demo-Code für ihre tolle Hardware fabrizieren die sie verkaufen wollen!?

Idealist!

> /*!
>     \brief      insert a delay time
>     \param[in]  nCount: stall Count
>     \param[out] none
>     \retval     none
> */
> void delay(uint32_t nCount)
> {
>     for(; nCount != 0; nCount--);
> }
>
> Was soll der Scheiß? Dieser Code tut nichts, der Compiler wirft also
> zurecht die ganze Funktion raus.

Nur wenn der Optimierer einschaltet ist.

> Was erwartet der Programmierer? Daß

Eine Zählschleife zum Zeit vertrödeln.

> Wann hört das endlich auf, wann fangen die endlich an logisch zu denken

Das ist schon logisch, aber halt Erstsemestlerlogik. 
Compileroptimierungen von ungenutzten Variablen kommen erst in den 
höheren Semestern. ;-)

> und eventuell vielleicht sogar die Sprache zu lernen die sie den ganzen
> Tag lang benutzen?

Reg dich nicht auf, auch TI hat da so seine Spezialitäten. Als ich vor 
knapp drei Jahren mit dem PICCOLO angefangen habe, hatte ich am 
Anfang auch ein paar kleine WTF-Erlebnisse. Mein persönliches Highlight 
war die Tatsache, daß der Compiler (Code Composer Studio 6.0 mit Control 
Suite ??) es NICHT automatisch fertig bringt, nicht initialisierte, 
globale Variablen sowie ebenfalls nicht initialisierte statische lokale 
Variablen zu nullen. Das steht zwar relativ explizit im 
Compilerhandbuch, wenn man mal die Stelle gefunden hat, aber warum 
bitteschön liefert man SÄMTLICHE Demos mit diesem Stand aus? Zumal der 
Fix dafür TRIVIAL ist, wenn man ein eingearbeiteter Profi mit dem 
System/Compiler ist. Man muss nur ein winziges Stück Startup-Code in ASM 
anpassen und schon geht es! Mann O Mann. Der Scheiß hat mich drei Tage 
Rätseln und Fluchen gekostet!

von Dr. Sommer (Gast)


Lesenswert?

Falk B. schrieb:
> Reg dich nicht auf, auch TI hat da so seine Spezialitäten.

Ich glaub das ist bei allen Halbleiterherstellern so. Da arbeiten nur 
Ingenieure, die stellen aus Prinzip keine Informatiker ein und 
programmieren nach "Das haben wir schon immer so gemacht"-Prinzip. Da 
Platinendesign und Bauteilauswahl bei deren Kunden auch von Ings gemacht 
wird, verstehen die sich bestens...

Wenn man sich den Code anschaut den Microchip so abgibt möchte man 
weinen, da ist so eine Dummy-Schleife noch harmlos. Mein persönlicher 
Favorit:
1
nm_bsp_sleep(1); /* TODO: Why bus error if this delay is not here. */
Fehlerbehandlung ist da auch "Mut zur Lücke". Man sehnt sich geradezu 
nach der schönen sauberen stabilen Arduino-Umgebung...

von Spezialisten-Experte für Koryphaen-Suche (Gast)


Lesenswert?

Bernd K. schrieb:
> Man sollte meinen eine Firma wie GigaDevices könnte Leute beschäftigen
> die der Sprache C mächtig sind, zumindest in der Abteilung die den
> Demo-Code für ihre tolle Hardware fabrizieren die sie verkaufen wollen!?


Bewirb Dich doch. So jemanden wie Dich haben sie bestimmt noch nie in 
ihren Reihen gehabt. Deine Chancen waren nie so hoch wie heute.

von vn nn (Gast)


Lesenswert?

Falk B. schrieb:
> Mein persönliches Highlight
> war die Tatsache, daß der Compiler (Code Composer Studio 6.0 mit Control
> Suite ??) es NICHT automatisch fertig bringt, nicht initialisierte,
> globale Variablen sowie ebenfalls nicht initialisierte statische lokale
> Variablen zu nullen.

Du meinst das hier?
http://processors.wiki.ti.com/index.php/Uninitialized_Static_Objects_Not_Set_to_Zero_in_COFF

Ja, been there, done that.

Money quote:
> Isn't that a violation of the C standard?
>
> This is not technically a violation of the C standard, since the linker is > 
part of the implementation, and a method is provided for the user to get
> the job done, but this method is very unintuitive, and many consider it a
> violation. It is certainly an obstacle to ease of use.

von Sebastian R. (sebastian_r569)


Lesenswert?

Dr. Sommer schrieb:
> Ich glaub das ist bei allen Halbleiterherstellern so. Da arbeiten nur
> Ingenieure, die stellen aus Prinzip keine Informatiker ein und
> programmieren nach "Das haben wir schon immer so gemacht"-Prinzip.

Die Frage ist, worum geht es µC-Herstellern in ihren Beispielen?

Zu zeigen, wie man etwas lösen könnte, dass irgendwie funktioniert und 
das Prinzip zeigt oder darum, eine perfekte, bugfreie Lösung zu 
präsentieren, die nach allen Regeln der Kunst wasserdicht und total 
hübsch ist?

Ich finde es schon okay, wenn Halbleiter sind auf das konzentrieren, was 
sie können sollten. Silizium schnitzen. Insofern kann ich mit 
halbfertigen Firmware-Vorschlägen besser leben, als mit Bugs im 
Silizium, denn einen so feinen Lötkolben besitze ich nicht, als dass ich 
die beheben könnte ;)
Firmware/Code hingegen kann ich recht einfach fixen und an meine 
Bedürfnisse anpassen.

von Dr. Sommer (Gast)


Lesenswert?

Sebastian R. schrieb:
> Firmware/Code hingegen kann ich recht einfach fixen und an meine
> Bedürfnisse anpassen.

Dann fixe doch mal die STM32 HAL und was da sonst noch so an 
Vendor-Libraries rumgeistert... Natürlich in deiner Freizeit, weil im 
Projekt-Budget steht nichts von "Herstellerfehler ausbügeln". Das Ganze 
beschränkt sich ja nicht auf Beispiele sondern auch auf Bibliotheken, 
auf die man teilweise angewiesen ist, weil die entsprechende Hardware 
nicht dokumentiert ist und nur die Bibliothek das Interface kennt.

von Falk B. (falk)


Lesenswert?

Dr. Sommer schrieb:
> Falk B. schrieb:
>> Reg dich nicht auf, auch TI hat da so seine Spezialitäten.
>
> Ich glaub das ist bei allen Halbleiterherstellern so. Da arbeiten nur
> Ingenieure, die stellen aus Prinzip keine Informatiker ein

Auch Ings können gescheit programmieren, zumindest einige ;-)

> here. */Fehlerbehandlung ist da auch "Mut zur Lücke". Man sehnt sich
> geradezu
> nach der schönen sauberen stabilen Arduino-Umgebung...

KISS  ;-)

von Sebastian R. (sebastian_r569)


Lesenswert?

Auch der STM32 HAL ist nur eine kostenlose Beigabe zum Silizium, das man 
kauft.
Und auch STM32 geht bare metal. Aber meist merkt man die Fehler in der 
HAL ja erst, wenn es schon zu spät ist.


Über C-Standard-Libs können wir sprechen. Allerdings sind die ja 
meistens ausreichend von sehr vielen Nutzern getestet und frei von 
groben Macken.

von Gerd E. (robberknight)


Lesenswert?

Sebastian R. schrieb:
> Firmware/Code hingegen kann ich recht einfach fixen und an meine
> Bedürfnisse anpassen.

aber nur, solange die Datenblätter und Ref Manuals ausreichend Details 
hergeben bzw. die Firmware als Source bereitgestellt wird.

Der Trend geht aber leider dahin, daß Teile der Firmware nur noch als 
Blobs bereitgestellt werden und große Teile des Datenblatts nur mit 
großen Mühen und unter NDA oder teils auch überhaupt gar nicht 
erhältlich sind. Vor allem in den Bereichen Funk und Grafikcontroller 
ist das leider weit verbreitet, aber auch andere Bereiche holen auf :(

Und der selbe Schlag von Programmierern, der die hier im Thread 
zitierten Stilblüten produziert hat, wirkt dort dann auch an diesen 
Blobs mit...

von Dr. Sommer (Gast)


Lesenswert?

Genau diese Erfahrung hab ich auch gemacht! Das Produkt wird einem dann 
als das Beste seit geschnitten Brot verkauft (kann insb. auch Krebs 
heilen), aber dass man die Software nicht vernünftig eingebunden bekommt 
ist ja nur ein Detail...

von Markus F. (mfro)


Lesenswert?

vn nn schrieb:
> Du meinst das hier?
> 
http://processors.wiki.ti.com/index.php/Uninitialized_Static_Objects_Not_Set_to_Zero_in_COFF
>
> Ja, been there, done that.
>
> Money quote:
>> Isn't that a violation of the C standard?
>>
>> This is not technically a violation of the C standard, since the linker is >
> part of the implementation, and a method is provided for the user to get
>> the job done, but this method is very unintuitive, and many consider it a
>> violation. It is certainly an obstacle to ease of use.

Cool. "Unser Compiler ist standardkonform. Nur der Linker macht Mist, 
und das geht keinen was an" ;).

Weil's ja auch der Linker ist (und nicht das execution environment, 
das im Standard explizit definiert ist), der für's Initialisieren 
zuständig ist...

von Jim M. (turboj)


Lesenswert?

Du musst uralten Code erwischt haben, als der Compiler für die Plattform 
noch keinen funktionierenden Optimizer hatte.


Ich sehe moderne Varianten dieses Codes z.B. auf Github:
1
void Delay(__IO uint32_t nCount);
2
3
/**
4
  * @brief  Inserts a delay time.
5
  * @param  nCount: specifies the delay time length.
6
  * @retval None
7
  */
8
void Delay(__IO uint32_t nCount)
9
{
10
  for(; nCount != 0; nCount--);
11
}

Das unscheinbare __IO Makro steht natürlich fürs volatile Keyword.

Schlechter Stil ist das trotzdem, denn bei modernen MCUs dreht man auch 
gerne mal am CPU Takt.

von jemand (Gast)


Lesenswert?

Lustig. Genau so hat mein erstes Delay damals auch ausesehen.

Das lief wunderbar, bis ich mal die Optimierungen eingeschaltet habe. 
Dann war Kopfkratzen angesagt. Als reiner Hobbypfuscher ohne allzu große 
Vorbildung in Sachen Programmierung dauerte es schon etwas länger, bis 
ich die Ursache gefunden habe.

Das einzige noch "lustigere" Thema war Cache-Kohärenz beim Umstieg auf 
PIC32MZ. Was habe ich gesucht. Ich wusste ja nicht einmal, dass es sowas 
überhaupt gibt...

Daher Danke für den "rant". Wenn nur ein Anfänger das liset und 
versteht, ist schon viel gewonnen.

von Bernd K. (prof7bit)


Lesenswert?

Sebastian R. schrieb:
> Die Frage ist, worum geht es µC-Herstellern in ihren Beispielen?
>
> Zu zeigen, wie man etwas lösen könnte, dass irgendwie funktioniert und
> das Prinzip zeigt oder darum, eine perfekte, bugfreie Lösung zu
> präsentieren, die nach allen Regeln der Kunst wasserdicht und total
> hübsch ist?

In dem Fall lief der Code auf subtile Weise überhaupt nicht, bzw tat 
nicht das was er sollte und die Hardware die der Hersteller zu 
demonstrieren beabsichtigte tat nicht das gewünschte.

von Dr. Sommer (Gast)


Lesenswert?

jemand schrieb:
> Das einzige noch "lustigere" Thema war Cache-Kohärenz beim Umstieg auf
> PIC32MZ.

Das können die Cortex-A auch... Ist das bei den PIC32 noch gemeiner?

von Sebastian R. (sebastian_r569)


Lesenswert?

In die For-Schleife ein nop und gut ist :D

von Falk B. (falk)


Lesenswert?

Sebastian R. schrieb:
> In die For-Schleife ein nop und gut ist :D

Ist immer noch Schrott, weil man so keine genaue Angabe hat, viel Zeit 
mit einem Durchlauf vertrödelt wird. Wenn schon, dann in ASM incl. 
Macro, um eine Zeit in Zyklen umzurechnen, abhängig von der 
CPU-Frequenz. So macht es der avr gcc und auch TI und sicher auch viele 
andere. Leider meinen viele "Programmierer" nur allzu oft, das Fahrrad 
neu erfinden zu müssen. Leider hat es dann eher fünfeckige Räder . . .

von Dr. Sommer (Gast)


Lesenswert?

Auch ein schönes Beispiel, aus der USB-Bibliothek von NXP:
1
for( DWORD n = 0; n < (cnt + 3) / 4; n++ ) {
2
  *((__packed uint32_t *)dataPtr) = *((__packed uint32_t *)ptr);
3
  dataPtr += 4;
4
  ptr++;
5
}
Allein schon dieses DWORD, aber darum gehts nicht... Es geht darum, 
Daten in den USB-Speicher zu kopieren. Da hat sich wohl jemand gedacht 
dass es effizienter ist wenn man 32bit-Wörter kopiert statt einzelne 
Bytes. Nur leider ist das ganze für einen Cortex-M0, welcher keine 
unaligned Speicherzugriffe kann - die Zeiger sind aber manchmal 
unaligned. Daher wurde wohl das __packed hinzugefügt, welches 
(vermutlich) manche Compiler anweist, hier keine unaligned 
Speicherzugriffe durchzuführen, und stattdessen einzelne Bytes zu 
lesen/schreiben. Leider klappt das aber mit dem GCC nicht und stürzt ab. 
Absurderweise wird es auch wenn es funktionieren würde langsamer; hier 
uint32_t zu verwenden ist einfach kompletter Blödsinn. Ein ganz 
schlichtes
1
memcpy (dataPtr, ptr, n);
ist schneller, kompakter und korrekt. Optimal wäre natürlich dafür zu 
sorgen dass die Pointer immer aligned sind, dann hätte die ganze 
Speicherverwaltung geändert werden müssen.

von Bernd K. (prof7bit)


Lesenswert?

Jim M. schrieb:
> Du musst uralten Code erwischt haben, als der Compiler für die Plattform
> noch keinen funktionierenden Optimizer hatte.
>
> Ich sehe moderne Varianten dieses Codes z.B. auf Github:

Die auf GitHub sind wahrscheinlich von STM. GigaDevice stellt die 
preiswerten STM32-Klone und STM32-ähnlichen in China her und hat auch 
noch nicht die STM32-HAL sondern liefert Definitionen und 
Hilfsfunktionen für die Hardware in einem Ordner namens 
"standard_peripheral", copyright 2017 GigaDevice. Der betreffende Code 
ist in der main.c einer Demo für die TSI-Hardware (Touch sensor) auf 
einem von deren schweineteuren Demo-Boards.

Er lag dem Ding auf einer gebrannten CD bei.

von Bernd K. (prof7bit)


Lesenswert?

Hier noch so ein Klopfer, mein Compiler hat mir erstmal nen Fehler um 
die Ohren gehauen (-Wall -Wextra -Werror).

Wer findet den Fehler ohne den Compiler anzuwerfen?
1
unsigned char num[10]={0,1,2,3,4,5,6,7,8,9};
2
3
/*!
4
    \brief      number display test
5
    \param[in]  none
6
    \param[out] none
7
    \retval     none
8
*/
9
void num_test(void)
10
{
11
    uint8_t i=0;
12
    lcd_clear(BLUE);
13
    gui_draw_font_gbk24(16,20,YELLOW,BLUE, "Num Display Test");
14
15
    for(i=0; i<10; i++){
16
        gui_draw_font_num32(50+(i%3)*40,32*(i/3)+50,WHITE,BLUE,num[i+1]);
17
        delay_ms(100);
18
    }
19
20
    delay_ms(1000);
21
}

von Dr. Sommer (Gast)


Lesenswert?

Bernd K. schrieb:
> num[i+1]

Buffer Overflow...

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Bernd K. schrieb:
> num[i+1]

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Bernd K. schrieb:
> ,num[i+1]

num ist 10 Elemente groß, i läuft von 0 bis 9.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Dr. Sommer schrieb:
> Buffer Overflow...

Falsch ;-)

Der Buffer läuft nicht über, es wird nur ins Klo gegriffen.

von Dr. Sommer (Gast)


Lesenswert?

Ein Lesezugriff über Arraygrenzen hinweg ist genau so falsch wie ein 
Schreibzugriff. Ob man jetzt nur das eine oder auch das andere als 
Buffer Overflow bezeichnet ist dann auch egal...

von Bernd K. (prof7bit)


Lesenswert?

eval_board/Soft_Drive/tft_test.c:33:67: warning: iteration 9 invokes 
undefined behavior [-Waggressive-loop-optimizations]

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Dr. Sommer schrieb:
> Ein Lesezugriff über Arraygrenzen hinweg ist genau so falsch wie ein
> Schreibzugriff.

Richtig.

> Ob man jetzt nur das eine oder auch das andere als
> Buffer Overflow bezeichnet ist dann auch egal...

Nicht richtig. Einen Exploit bekommt man mittels Buffer Overflow 
leichter hin. Versuch das mal hinzubekommen, wenn das Programm lediglich 
danebengreift.

von Dr. Sommer (Gast)


Lesenswert?

Frank M. schrieb:
> Versuch das mal hinzubekommen, wenn das Programm lediglich
> danebengreift.

Hat Heartbleed nicht genau das gemacht?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Bernd K. schrieb:
> Wer findet den Fehler ohne den Compiler anzuwerfen?
                       ------------------------------

Bernd K. schrieb:
> eval_board/Soft_Drive/tft_test.c:33:67: warning: iteration 9 invokes
> undefined behavior [-Waggressive-loop-optimizations]

Du hast geschummelt :-)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Dr. Sommer schrieb:
> Hat Heartbleed nicht genau das gemacht?

Jein :-)

Man konnte dem Server unberechtigterweise Daten entlocken, aber keine 
unterschieben, wie man es beim Buffer-Overflow macht.

Aber das ist jetzt Haarspalterei, sehe ich ein.

von Silc P. (silch12)


Lesenswert?

Dr. Sommer schrieb:
> Ein Lesezugriff über Arraygrenzen hinweg ist genau so falsch wie ein
> Schreibzugriff. Ob man jetzt nur das eine oder auch das andere als
> Buffer Overflow bezeichnet ist dann auch egal...

Man nennt das einen Buffer-overread.

von HyperMario (Gast)


Lesenswert?

Falk B. schrieb:
> es NICHT automatisch fertig bringt, nicht initialisierte,
> globale Variablen sowie ebenfalls nicht initialisierte statische lokale
> Variablen zu nullen.

Das machen andere embeddedC Compiler nicht anders und es wird auch 
explizit darauf hingewiesen.

Das ist imo der Kompatibilität mit kleinen bis sehr kleinen Controllern 
geschuldet. Es spart Code und startet etwas schneller.

Ist auch sinnvoll da nach einem Reset noch die alten Werte vorhanden 
sind.

von Bernd K. (prof7bit)


Lesenswert?

Frank M. schrieb:
> Du hast geschummelt :-)

Ich hatte keine Wahl, der Compiler war schneller. Ich versuchte den 
Codehaufen gleich nach dem Auspacken mal locker-flockig zu kompilieren 
(hätte ja evtl funktionieren können) ohne ihn vorher komplett zu lesen.

von HyperMario (Gast)


Lesenswert?

Bernd K. schrieb:
> Was soll der Scheiß? Dieser Code tut nichts,

Sieht schräge aus, vielleicht eine Zeitschleife?

Wenn die Eingangsvariable global volatile ist wird Sie imo auch nicht 
wegoptimiert ;-).

von Falk B. (falk)


Lesenswert?

HyperMario schrieb:

> Das machen andere embeddedC Compiler nicht anders und es wird auch
> explizit darauf hingewiesen.

Jaja, im Dritten Absatzt von 500 Seiten Compilerhandbuch. Komisch, 
andere Compiler und IDEs können das, ohne daß der Anwender sich drum 
kümmern muß.
Das ist eine typische Juristenausrede.

> Das ist imo der Kompatibilität mit kleinen bis sehr kleinen Controllern
> geschuldet. Es spart Code und startet etwas schneller.

Diese dämliche Ausrede steht auch auf der TI-Seite. Dämlicher geht es 
kaum.
Wir reden von einer TRIVIALEN Schleife, die Nullen in einen 
Speicherblock schreibt. Flashbedarf vielleich 10 Bytes, Laufzeit ein 
paar hundert bist tausende Takte.

> Ist auch sinnvoll da nach einem Reset noch die alten Werte vorhanden
> sind.

Nö, dafür hat C andee Mechanismen parat, irgendwelche .noinit Sections.

von Bernd K. (prof7bit)


Lesenswert?

HyperMario schrieb:
> Falk B. schrieb:
>> es NICHT automatisch fertig bringt, nicht initialisierte,
>> globale Variablen sowie ebenfalls nicht initialisierte statische lokale
>> Variablen zu nullen.
>
> Das machen andere embeddedC Compiler nicht anders und es wird auch
> explizit darauf hingewiesen.

Das hat nichts mit dem Compiler zu tun, das passiert im Startup-Code. 
Der Compiler, der Linker und der Anwender sollten sich darauf verlassen 
können dass dort alle notwendigen Dinge getan werden bzw. aufgerufen 
werden so daß beim Eintritt in die main alle Garantien des Standards 
erfüllt sind (globale/statische Variablen initialisiert, statische 
Konstruktoren alle aufgerufen, etc.). Wenn der Startupcode fehlerhaft 
ist funktioniert schlimmstenfalls gar nichts.

von vn nn (Gast)


Lesenswert?

HyperMario schrieb:
> Ist auch sinnvoll da nach einem Reset noch die alten Werte vorhanden
> sind.

Aber klar doch.


Falk B. schrieb:
> Wir reden von einer TRIVIALEN Schleife, die Nullen in einen
> Speicherblock schreibt. Flashbedarf vielleich 10 Bytes, Laufzeit ein
> paar hundert bist tausende Takte.

Und das, nebenbei bemerkt, auf einem 100MHz-DSP. Außerdem würde man 
diese Ausrede vielleicht noch gelten lassen, würde der Compiler nicht 
folgendes geniale Verhalten aufweisen:

Preisfrage: bei erwähntem TI Compiler, was steht in bar (bzw. foo[1])? 
Was würde man sich erwarten?
1
unsigned char foo[3] = { 0 };
2
3
int main (void) {
4
    unsigned char bar = foo[1];
5
6
    while (1) ;
7
}

von Falk B. (falk)


Lesenswert?

Bernd K. schrieb:
> HyperMario schrieb:
>> Falk B. schrieb:
>>> es NICHT automatisch fertig bringt, nicht initialisierte,
>>> globale Variablen sowie ebenfalls nicht initialisierte statische lokale
>>> Variablen zu nullen.
>>
>> Das machen andere embeddedC Compiler nicht anders und es wird auch
>> explizit darauf hingewiesen.
>
> Das hat nichts mit dem Compiler zu tun, das passiert im Startup-Code.

OK, das Gesamtsystem muß passen. Üblicherweise liefern Hersteller von 
Compilern und IDEs dieses aber in einem SINNVOLLEN Zustand aus, der 
erstmal KEINE elementaren Nacharbeiten erfordert. Die Jungs bei TI haben 
schlicht gepennt und die paar Zeilen im ohnehin vorhandenen 
Startup-Fragment vergessen.

von Bernd K. (prof7bit)


Lesenswert?

vn nn schrieb:

>
> Preisfrage: bei erwähntem TI Compiler, was steht in bar (bzw. foo[1])?
> Was würde man sich erwarten?
>
>
1
> unsigned char foo[3] = { 0 };
2
> 
3
> int main (void) {
4
>     unsigned char bar = foo[1];
5
> 
6
>     while (1) ;
7
> }
8
>

Ich würde erwarten daß das Programm auf folgendes zurechtgestutzt wird 
und weder foo noch bar überhaupt existieren weil sie überhaupt nicht 
werden:
1
> int main (void) {
2
>     while (1) ;
3
> }

von HyperMario (Gast)


Lesenswert?

Falk B. schrieb:
> Wir reden von einer TRIVIALEN Schleife, die Nullen in einen
> Speicherblock schreibt. Flashbedarf vielleich 10 Bytes, Laufzeit ein
> paar hundert bist tausende Takte.
>

Es gibt nun mal Controller wo das viel Platz ist. Gerade bei 
Massenprodukten wird gespart wo es geht.

Bin in die Falle auch gelaufen, hat mich sagenhafte 30 Minuten gekostet 
das festzustellen und das Problem im Forum via Google zu finden.

>> Ist auch sinnvoll da nach einem Reset noch die alten Werte vorhanden
>> sind.
>
> Nö, dafür hat C andee Mechanismen parat, irgendwelche .noinit Sections.

Wenn du meinst [SchulterzuckEmoticon]

von HyperMario (Gast)


Lesenswert?

Bernd K. schrieb:
> Das hat nichts mit dem Compiler zu tun, das passiert im Startup-Code.
> Der Compiler, der Linker und der Anwender sollten sich darauf verlassen
> können dass dort alle notwendigen Dinge getan werden bzw. aufgerufen
> werden so daß beim Eintritt in die main alle Garantien des Standards
> erfüllt sind

Die embedded Welt hat nun mal Abweichungen vom Standard. Kann man jetzt 
anklagen, in diesem Fall sind Sie aber imo sinnvoll. Denke mir auch das 
sich die Entwickler was dabei gedacht haben.

von Dr. Sommer (Gast)


Lesenswert?

HyperMario schrieb:
> Es gibt nun mal Controller wo das viel Platz ist. Gerade bei
> Massenprodukten wird gespart wo es geht.

Wenn man in die Verlegenheit kommt, ein paar Bytes zu sparen, kann man 
die Schleife immer noch rausnehmen. Die Grundkonfiguration von Compiler, 
Linker, Libs, Startup-Code, Linker-Script sollte das am Wenigsten 
überraschende ganz normale C-Verhalten bieten. Sonderwünsche kann man 
sich bei Bedarf immer noch selbst einbauen.

von Bernd K. (prof7bit)


Lesenswert?

HyperMario schrieb:
> Es gibt nun mal Controller wo das viel Platz ist. Gerade bei
> Massenprodukten wird gespart wo es geht.

Und das umständliche manuelle Nullen von jeder einzelnen globalen oder 
statischen Variable die mit 0 starten soll braucht dann weniger Platz 
oder was?

von Falk B. (falk)


Lesenswert?


von HyperMario (Gast)


Lesenswert?

Bernd K. schrieb:
> Und das umständliche manuelle Nullen von jeder einzelnen globalen oder
> statischen Variable die mit 0 starten soll braucht dann weniger Platz
> oder was?

Nein, vermutlich sogar mehr. Aber es gibt wohl Gründe warum man es so 
macht, auch wenn Sie einem nicht passen.

Wat dem een sin Uhl is dem annern sin Nachtigall ;-).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

HyperMario schrieb:
> Das machen andere embeddedC Compiler nicht anders und es wird auch
> explizit darauf hingewiesen.

Dann sollen sie die Sprache, die sie vorzugeben zu compilieren, aber 
bitte nicht C nennen … D, nee, gibt's auch schon … X vielleicht?

C hat einen Standard, auf den sollte man sich verlassen können. Wenn ich 
mich nicht auf die globalen und statischen Variablen verlassen kann, wer 
garantiert mir denn dann, dass ich mich darauf verlassen kann, dass 
main() überhaupt ausgeführt wird?  Vielleicht muss ich ja erst ein Stück 
Assemblercode mitliefern, welches main() startet, weil es in 
pathologischen Fällen schneller ist, auf dessen Start zu verzichten?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

HyperMario schrieb:
> Die embedded Welt hat nun mal Abweichungen vom Standard. Kann man jetzt
> anklagen, in diesem Fall sind Sie aber imo sinnvoll. Denke mir auch das
> sich die Entwickler was dabei gedacht haben.

Nein. Das sind kaputte Compiler. Auch im Embedded-Bereich.

Das darf nicht das Standardverhalten sein; richtige 
Entwicklungssysteme sehen hierfür eine eigene Sektion im Linkerskript 
o.ä. vor, in dem Variablen untergebracht werden können, die explizit 
nicht initialisiert werden.

Damit kann der Nutzer des Compilers selbst entscheiden, was er will, 
ohne komischen Code für Selbstverständlichkeiten schreiben zu müssen.

von HyperMario (Gast)


Lesenswert?

Jörg W. schrieb:
> hat einen Standard, auf den sollte man sich verlassen können.

Amen. Is nun mal so, kann man jetzt anklagen und sich auf sonstwen 
berufen.
Als Hüter der reinen Lehre hat man immer leicht reden. Man muss ja auch 
den
Code nicht in 1k Flash und 64 byte RAM unterbringen (da kommt das her).

> bitte nicht C nennen
Wie wäre es mit embedded C- compiler ;-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

HyperMario schrieb:
> Man muss ja auch den Code nicht in 1k Flash und 64 byte RAM unterbringen
> (da kommt das her).

Selbst da muss man Variablen initialisieren.

Wie Rufus schon schreibt, einen Weg, nicht automatisch initialisierte 
Datenbereiche zu haben, kann und sollte man zusätzlich vorsehen (und 
dokumentieren), aber nicht deshalb die restliche Welt auf den Kopf 
stellen.

>> bitte nicht C nennen
> Wie wäre es mit embedded C- compiler ;-)

Immer noch falsch. Ich habe so einen Quatsch noch nie gebraucht, auch 
nicht mit kleinen Controllern. Immer nur mal einzelne Variablen, die 
einen Reset unverändert überleben müssen.

von Bernd K. (prof7bit)


Lesenswert?

HyperMario schrieb:
>> bitte nicht C nennen
> Wie wäre es mit embedded C- compiler ;-)

Nohmal: Es ist nicht der Compiler sondern der vom Hersteller 
zusammengemurkste Startup-Code der heimlich die Arbeit des ahnungslosen 
Compilers sabotiert. Wäre es der Compiler würde er bei einer 
uninitialisierten globalen Variable warnen weil er dann wüßte das das 
undefiniert ist.

von Axel S. (a-za-z0-9)


Lesenswert?

Jörg W. schrieb:
> C hat einen Standard, auf den sollte man sich verlassen können. Wenn ich
> mich nicht auf die globalen und statischen Variablen verlassen kann, wer
> garantiert mir denn dann, dass ich mich darauf verlassen kann, dass
> main() überhaupt ausgeführt wird?  Vielleicht muss ich ja erst ein Stück
> Assemblercode mitliefern, welches main() startet, weil es in
> pathologischen Fällen schneller ist, auf dessen Start zu verzichten?

Nicht zu vergessen wieviel Flash man damit auch einsparen kann!!1!elf!

LOL. MMD.

von HyperMario (Gast)


Lesenswert?

Axel S. schrieb:
> Nicht zu vergessen wieviel Flash man damit auch einsparen kann!

wenn du 10 000 Stück Serie hast zählt manchmal jedes ByteRufus Τ. F. 
schrieb im Beitrag #5687466:
> Nein. Das sind kaputte Compiler. Auch im Embedded-Bereich.

Dann arbeite ich eben mit kaputten compilern, mir völlig egal. Die 
Unterschiede zu Standard C sind dokumentiert, machen Sinn und es wird 
niemand gezwungen damit zu arbeiten.


Rufus Τ. F. schrieb:
> Das darf nicht das Standardverhalten sein;

Is aber, und nu?

So, ich geh jetzt ein vergoldetes Steak essen, nur aus Renitenz ;-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

HyperMario schrieb:
>> Das darf nicht das Standardverhalten sein;
>
> Is aber, und nu?

Tonne auf, Toolchain rein, Tonne zu. :-)

Gibt doch genügend Alternativen, warum sollte ich mich mit einer 
Toolchain eines Herstellers rumärgern müssen, der alles besser weiß als 
etablierte Standards?

>> Nicht zu vergessen wieviel Flash man damit auch einsparen kann!
>
> wenn du 10 000 Stück Serie hast zählt manchmal jedes Byte

Du hattest übrigens den Witz nicht verstanden.

Es ging darum, dass main() eben auch gleich nicht mehr aufgerufen wird …

: Bearbeitet durch Moderator
von Marten Morten (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Ein Lesezugriff über Arraygrenzen hinweg ist genau so falsch wie ein
> Schreibzugriff. Ob man jetzt nur das eine oder auch das andere als
> Buffer Overflow bezeichnet ist dann auch egal...

Nein, korrekte Terminologie ist wichtig. Das hat Kommunikation halt so 
an sich wenn man verstanden werden will. Das ist, auf Englisch, ein 
Out-of-bounds array access.

von Vn N. (wefwef_s)


Lesenswert?

Bernd K. schrieb:
> Ich würde erwarten daß das Programm auf folgendes zurechtgestutzt wird
> und weder foo noch bar überhaupt existieren weil sie überhaupt nicht
> werden:

War ja klar dass die Korinthenkackerfraktion auftaucht, es handelt sich 
um ein sinngemäßes Beispiel,  denk dir halt den Optimizer weg oder ein 
volatile hin.

HyperMario schrieb:
> Es gibt nun mal Controller wo das viel Platz ist. Gerade bei
> Massenprodukten wird gespart wo es geht.

Aber nicht dieser konkrete Controller,  also lahme Ausrede.

HyperMario schrieb:
> Als Hüter der reinen Lehre hat man immer leicht reden. Man muss ja auch
> den Code nicht in 1k Flash und 64 byte RAM unterbringen (da kommt das
> her).

Trifft auf diesen Controller nicht zu.

HyperMario schrieb:
> wenn du 10 000 Stück Serie hast zählt manchmal jedes Byte

Für ungenutzten Flash gibts kein Geld zurück.

Jörg W. schrieb:
> Gibt doch genügend Alternativen, warum sollte ich mich mit einer
> Toolchain eines Herstellers rumärgern müssen, der alles besser weiß als
> etablierte Standards?

Zum C2000-Compiler gibts leider wenig Alternativen. Schade darum, hat 
interessante PWM-Hardware.

von Dieter F. (Gast)


Lesenswert?

Bernd K. schrieb:
> eine Firma wie GigaDevices

Sei mal nicht so knauserig und zeig den kompletten Code oder Link dahin.

Bernd K. schrieb:
> Demo-Code für ihre tolle Hardware

Welche denn?

von Thomas Maier (Gast)


Lesenswert?

Bernd K. schrieb:
> Was soll der Scheiß?

Welcher Scheiß?
Das ist gültiger C-Code.
Daran gibts nichts auszusetzen.

Bernd K. schrieb:
> der Compiler wirft also
> zurecht die ganze Funktion raus.

Nein. Tut er nicht. Jedenfalls nicht solange DU ihn nicht durch das 
Einschalten der Optimierung dazu zwingst.

Bernd K. schrieb:
> Was erwartet der Programmierer?

Genau das was er programmiert und bezweckt hat. In diesem Kontext tut 
dieser Programmschnipsel genau das was er tun soll. Das dir der 
Programmierstil nicht gefällt ist eine andere Sache. Aber schließe nicht 
von dir auf andere.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Thomas Maier schrieb:
> Bernd K. schrieb:
>> der Compiler wirft also
>> zurecht die ganze Funktion raus.
>
> Nein. Tut er nicht. Jedenfalls nicht solange DU ihn nicht durch das
> Einschalten der Optimierung dazu zwingst.

Es ist nicht garantiert, dass der Compiler erst dann optimiert, wenn Du 
irgendeine Optimierung einschaltest. Vielmehr muss der Compiler nur ein 
gewünschtes Resultat erfüllen. Ein Delay über eine sinnlose Zählschleife 
muss er jedoch nicht garantieren - egal ob irgendeine Optimierung 
eingeschaltet ist oder nicht.

Daher muss ich Dich korrigieren. Richtig ist:

Du kannst von Glück reden, wenn er ohne Optimierungs-Option die Schleife 
tatsächlich in Code umsetzt. Meist ist es tatsächlich so - vielleicht 
machen dies die Compilerbauer aus purem Mitleid.

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Thomas Maier schrieb:
> Jedenfalls nicht solange DU ihn nicht durch das Einschalten der
> Optimierung dazu zwingst.

Das ist so ziemlich das hanebüchenste Argument bislang im ganzen Thread.

Praktisch jeder möchte gut optimierten Code haben. Den Leuten dann zu 
sagen, dass sie bitteschön die Optimierung deaktivieren sollen, damit 
eine krückig implementierte Verzögerungsschleife auch tatsächlich einen 
Effekt hat, ist doch komplett absurd.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jörg W. schrieb:
> Den Leuten dann zu sagen, dass sie bitteschön die Optimierung
> deaktivieren sollen, damit eine krückig implementierte
> Verzögerungsschleife auch tatsächlich einen Effekt hat, ist doch
> komplett absurd.

Aber durchaus Realität:

http://mikrocontroller.bplaced.net/wordpress/?page_id=142

Siehe Abschnitt 3. Leider sind die dort angesprochenen "Fehler" nicht 
nur auf Zeitschleifen begrenzt. In Uwes Codebeispielen (die ich sonst 
sehr schätze) fehlt auch öfter mal das magische Keyword "volatile", zum 
Beispiel bei DMA-Transfers, die dann nur funktionieren, wenn man die 
Optimierung abschaltet.

(Ich hatte ihn damals darauf hingewiesen, er hatte es leider mit einem 
lapidaren "kann sein" abgetan)

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Frank M. schrieb:
> Aber durchaus Realität:

Pah.

Das erinnert mich an denjenigen, der hier mal zum besten gegeben hat, 
dass die Steuerungen in einer früheren Firma, in der er tätig war, 
allesamt ohne Interrupts auskommen mussten, weil der Firmenchef 
Interrupts nie verstanden hat. =:-}

von Bernd K. (prof7bit)


Lesenswert?

Thomas Maier schrieb:
> Bernd K. schrieb:
>> Was erwartet der Programmierer?
>
> Genau das was er programmiert und bezweckt hat.

Ja, und er hat genau nichts programmiert! Er hat programmiert daß an 
der Stelle genau nichts zu tun ist. Nada! Niente! Er hat eine Funktion 
geschrieben die genau NICHTS tut und auch KEINEN Rückgabewert hat. 
Wenn der Compiler das also möglichst genau umsetzen will erzeugt er 
einfach an der Stelle überhaupt keinen Code. Ist das so schwer zu 
verstehen?

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

Jörg W. schrieb:
> Frank M. schrieb:
>> Aber durchaus Realität:
>
> Pah.
>
> Das erinnert mich an denjenigen, der hier mal zum besten gegeben hat,
> dass die Steuerungen in einer früheren Firma, in der er tätig war,
> allesamt ohne Interrupts auskommen mussten, weil der Firmenchef
> Interrupts nie verstanden hat. =:-}

Vielleicht hat er das auch mit Paragraph 218 verwechselt . . . 8-0

von Dr. Sommer (Gast)


Lesenswert?

Jörg W. schrieb:
> weil der Firmenchef
> Interrupts nie verstanden hat. =:-}

In der "Websiten-AG" meiner Schule damals™ konnten keine serverseitigen 
Scripte verwendet werden (PHP war alternativlos), weil der betreuende 
Lehrer sie nicht verstanden hatte. Daher war alles statisches HTML (auch 
ohne JS) - inklusive der Windows Explorer-artig aufklappenden 
Navigation. Wegen dieser roten Flagge bin ich direkt wieder gegangen ;-)

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.