Bei meiner Beschäftigung mit dem Raspberry Pi ist eine umfangreiche C-Werkstatt entstanden. Ich würde gerne im Sinne des Open Source Gedankens etwas zurückgeben und suche einen Autor für ein Buch oder einen Blog rund um das Thema 'Praktischer Einsatz von C'. Das Ergebnis können Sie unter http://www.schmuckhexen.at [Projekt /c] einsehen. Vorwort http://www.schmuckhexen.at/programs/c/clar_vorwort.pdf. Kapitel: 'Projekt c/' und 'Autoren gesucht' Vielleicht können Sie mir weiterhelfen. Danke Günther Schardinger, Austria, Trofaiach Webseite : http://www.schmuckhexen.at/ Websuche : schardinger linux c eMail : v.schardinger@gmx.net
Günther S. schrieb: > Ich würde gerne im Sinne des Open Source Gedankens etwas zurückgeben und > suche einen > Autor für ein Buch Verstehe ich nicht. Wenn du etwas zurück geben willst, dann bist DU der Autor.
Günther S. schrieb: > Bei meiner Beschäftigung mit dem Raspberry Pi ist eine umfangreiche > C-Werkstatt entstanden. Hmm. Was ist eine C-Werkstatt? Und Linux gibt es seit über 30 Jahren, C noch länger. Da gibt es schon gefühlt 1000 Tutorials. Der RasPi ist halt nur eine (weitere) Plattform auf der Linux läuft. Versteh mich nicht falsch. Ich will das nicht madig machen. Es sieht nach viel Arbeit aus. Und einige der o.a. Tutorials sind schlechter als deins. Trotzdem stellt sich halt die Frage nach dem Sinn. Hoffentlich hattest du wenigstens Spaß dabei. > Ich würde gerne im Sinne des Open Source Gedankens etwas zurückgeben und > suche einen > Autor für ein Buch oder einen Blog rund um das Thema 'Praktischer > Einsatz von C'. > > Das Ergebnis können Sie unter http://www.schmuckhexen.at [Projekt /c] > einsehen. Sieht doch gut aus. Wozu brauchst du da noch einen (weiteren) Autor? Wird es dir zuviel? Dann hör auf.
Danke für Beiträge. Ein paar Antworten: 1. Die Werkstatt Projekt /c erleichtert das Programmieren mit C. 2. Wiso und Warum unter: https://www.projektc.at/programs/c/clar_vorwort.pdf 3. Das Ausprobieren der Werkstatt ist sehr einfach: https://www.projektc.at/programs/c/clar_start.pdf 4. Die Sprache C ist zwar sehr einfach. Die Projektorganisation nicht. 5. Projekt /c bietet umfangreiche Lösungen zu den Defiziten von C. Neues Beispiel: Programm 'wwwtool' zum Bearbeiten/Warten von Webseiten. Siehe: https://www.projektc.at/programs/c_bsp/wwwtool/index.html Servus, Günther
Günther S. schrieb: > Danke für Beiträge. Es wäre vermutlich sinnvoll, Deinen früheren Thread zu verlinken.
Die ganze Seite gibt mir nostalgische Gefühle. Was soll der Unsinn? Günther S. schrieb: > Neues Beispiel: Programm 'wwwtool' zum Bearbeiten/Warten von Webseiten. So erstellt und wartet niemand seit 1995 mehr Webseiten. Ehrliche Frage: Was denkst du in welchem Jahr wir uns aktuell befinden? Wann bist du hängengeblieben?
:
Bearbeitet durch User
Ein T. schrieb: > Es wäre vermutlich sinnvoll, Deinen früheren Thread zu verlinken. Ich habe beide Threads (den alten und den neuen) zusammengeführt. An Günther S. (projekt_c): Bitte nicht jedesmal einen neuen Thread öffnen, sondern den bereits vorhandenen Thread nutzen, solange es kein neues Thema ist.
:
Bearbeitet durch Moderator
Frank M. schrieb: > An Günther S. (projekt_c): Bitte nicht jedesmal einen neuen Thread > öffnen, sondern den bereits vorhandenen Thread nutzen, solange es kein > neues Thema ist. Der Günther macht eh immer nur Fire and Forget und geht auf nichts ein. Im Grunde spamt er nur Werbung für seine Seite.
:
Bearbeitet durch User
Ist doch wunderbar das Projekt! Wo kann man sonst schon 30 Jahre in die Vergangenheit reisen, ganz ohne Wayback-Machine und Flux-Kompensator.
Ich habe die Erklärungen zu Projekt /c durch Grundlegende Konzepte und weiter Beispiele erweitert. Webseite : https://www.projektc.at
Günther S. schrieb: > Ich habe die Erklärungen zu Projekt /c durch > Grundlegende Konzepte und weiter Beispiele erweitert. > > Webseite : https://www.projektc.at Du schreibst: "Die geprüften Bibliotheken beheben Defizite der Linuxbibliothek 'Libc'. Beispiel: Libc Funktion strcmp(NULL,NULL) stürzt ab, die Funktionkopie StrCmp(NULL,NULL) nicht."
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <string.h> |
4 | |
5 | int
|
6 | main(void) |
7 | {
|
8 | |
9 | printf("res = %d\n", strcmp(NULL, NULL)); |
10 | |
11 | return EXIT_SUCCESS; |
12 | }
|
[bash] ~/C/test$ gcc -Wall -pedantic -std=c99 -o tstrcmp tstrcmp.c tstrcmp.c: In function ‘main’: tstrcmp.c:9:26: warning: argument 1 null where non-null expected [-Wnonnull] 9 | printf("res = %d\n", strcmp(NULL, NULL)); | ^~~~~~ In file included from tstrcmp.c:3: /usr/include/string.h:156:12: note: in a call to function ‘strcmp’ declared ‘nonnull’ 156 | extern int strcmp (const char *__s1, const char *__s2) | ^~~~~~ tstrcmp.c:9:26: warning: argument 2 null where non-null expected [-Wnonnull] 9 | printf("res = %d\n", strcmp(NULL, NULL)); | ^~~~~~ /usr/include/string.h:156:12: note: in a call to function ‘strcmp’ declared ‘nonnull’ 156 | extern int strcmp (const char *__s1, const char *__s2) | ^~~~~~ ~/C/test$ ./tstrcmp res = 0 ~/C/test$ echo $? 0 [/bash] Bei mir unter Debian/GNU-Linux mit gcc stürzt es nicht ab. gcc warnt vor der Verwendung der NULL-Pointer und strcmp liefert 0 zurück, da beide pointer gleich sind.
Alexander S. schrieb: > "Die geprüften Bibliotheken beheben Defizite der Linuxbibliothek 'Libc'. > Beispiel: Libc Funktion strcmp(NULL,NULL) stürzt ab, die Funktionkopie > StrCmp(NULL,NULL) nicht." Dem C-Standard zufolge ist das Übergeben von NULL-Pointern an strcmp "undefined behaviour", es darf also irgendwas passieren (Rückgabe 42, Programmabsturz, Festplatte formatiert). Es handelt sich also nicht um einen Fehler. Dass die gnu libc bei solch elementaren Funktionen fehlerhaft wäre, wäre auch sehr schwer vorstellbar...
Lieber Alexander! Danke für Deine Antwort! Ich habe nicht vor an C-Standard zu rütteln. Im Gegenteil: Dieser Standard hat es mir erst ermöglicht, Projekt /c zu implementieren. Basis ist nur Linux, gcc und Libc. Für mich geht es um die Möglichkeit umfangreiche Projekte zu realisieren und nicht um eine Programmiersprache. Beispiel: Schon das Hifsprogramm 'chelp' hat derzeit bereits 4791 Zeilen Programmcode. Da möchte ich nicht ständig auf NULL prüfen müssen. Meine Lösung: Zu strcmp(...) gibt es die geduldige Funktion StrCmp(..) Die Bibliotheksfunktionen von Projet /c bieten sichere und komplexe Systemaufrufe. Sie können aber müssen nicht verwendet werden! Vielleicht magst Du https://www.projektc.at einmal ausprobieren. Es lässt sich rückstandsfrei entfernen. Servus, Günther
Günther S. schrieb: > Da möchte ich nicht ständig auf NULL prüfen müssen So ist das aber halt wenn man in C programmiert - man macht alles von Hand, auch Fehlerbehandlung. In anderen Sprachen wie C++, Rust, Java, Python, Kotlin ... geht das viel einfacher.
Günther S. schrieb: > Beispiel: Schon das Hifsprogramm 'chelp' hat derzeit bereits 4791 Zeilen > Programmcode. Da möchte ich nicht ständig auf NULL prüfen müssen. > Meine Lösung: Zu strcmp(...) gibt es die geduldige Funktion StrCmp(..) Hallo Günther,
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <string.h> |
4 | |
5 | /* Aus ProjektC/c/lib/include/utils.h */
|
6 | int StrCmp(const char*a, const char *b); // wie strcmp(), case-sensitiv |
7 | |
8 | int
|
9 | main(void) |
10 | {
|
11 | |
12 | printf("res = %d\n", StrCmp(NULL, NULL)); |
13 | |
14 | return EXIT_SUCCESS; |
15 | |
16 | }
|
17 | |
18 | /* Aus ProjektC/c/lib/utils/utils.c */
|
19 | int StrCmp(const char*a, const char *b) |
20 | { if (!a && !b) return 0; |
21 | if (a && !b) return 1; |
22 | if (!a && b) return -1; |
23 | return strcmp(a,b); |
24 | } // -------------------------------------- |
1 | ~/C/test$ gcc -Wall -pedantic -std=c99 -o pstrcmp pstrcmp.c |
2 | ~/C/test$ ./pstrcmp |
3 | res = 0 |
4 | ~/C/test$ echo $? |
5 | 0 |
Zum Vergleich
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <string.h> |
4 | |
5 | int
|
6 | main(void) |
7 | {
|
8 | |
9 | printf("res = %d\n", strcmp(NULL, NULL)); |
10 | |
11 | return EXIT_SUCCESS; |
12 | |
13 | }
|
1 | ~/C/test$ gcc -Wall -pedantic -std=c99 -o tstrcmp tstrcmp.c |
2 | tstrcmp.c: In function ‘main’: |
3 | tstrcmp.c:9:26: warning: argument 1 null where non-null expected [-Wnonnull] |
4 | 9 | printf("res = %d\n", strcmp(NULL, NULL)); |
5 | | ^~~~~~ |
6 | In file included from tstrcmp.c:3: |
7 | /usr/include/string.h:156:12: note: in a call to function ‘strcmp’ declared ‘nonnull’ |
8 | 156 | extern int strcmp (const char *__s1, const char *__s2) |
9 | | ^~~~~~ |
10 | tstrcmp.c:9:26: warning: argument 2 null where non-null expected [-Wnonnull] |
11 | 9 | printf("res = %d\n", strcmp(NULL, NULL)); |
12 | | ^~~~~~ |
13 | /usr/include/string.h:156:12: note: in a call to function ‘strcmp’ declared ‘nonnull’ |
14 | 156 | extern int strcmp (const char *__s1, const char *__s2) |
15 | | ^~~~~~ |
16 | ~/C/test$ ./tstrcmp |
17 | res = 0 |
18 | ~/C/test$ echo $? |
19 | 0 |
D.h. StrCmp lässt sich mit NULL Pointern aufrufen ohne beim Compilieren eine Warnung zu erzeugen. Soll das der Vorteil ggü. strcmp der stdlib sein? Kannst Du genau beschreiben was der Vorteil von StrCmp ggü. strcmp der stdlib sein soll? Kannst Du genau beschreiben welche Defizite in "Die geprüften Bibliotheken beheben Defizite der Linuxbibliothek 'Libc'" gemeint sind. Was genau meinst Du mit "Zu strcmp(...) gibt es die geduldige Funktion StrCmp(..)". Meinst Du mit "geduldig" "unterdrückt Warnungen beim Compilieren und erlaubt die Verwendung von NULL Pointern"?
:
Bearbeitet durch User
Erstmal vielen Dank für diese konstruktive Diskusion!
1 | void Test() |
2 | { clrScr(); |
3 | printf("Laufzeit Test\n"); |
4 | char *s=NULL; |
5 | char *t=NULL; |
6 | printf("s=%s t=%s\n", StrN(s),StrN(t)); |
7 | printf("strcmp(s,s) ->%i\n", strcmp(s,t)); |
8 | |
9 | WeiterMitTaste(); |
10 | }
|
1 | Laufzeit Test |
2 | s=NULL t=NULL |
3 | Speicherzugriffsfehler (Speicherabzug geschrieben) |
Test mit gnuc 13.3.0 und Libc 2.39. Den Startwert für uninitialisierte Pointer und Objektpointer setze ich immer erstmals auf NULL. Ich wollte mir keine unnötige Arbeit aufhalsen. Als Einzellkämpfer macht Programmieren aber nur Spaß, wenn die eigenen Programme wirklich funktionieren. Trotz sorgfältiger Codierung wird es Fehler geben. Fehlermeldungen wie "Speicherzugriffsfehler (Speicherabzug geschrieben)" sehr sind mühsam. Meine Fehlermeldungen ermöglichen es sofort mit 'Text suchen' die Stelle im Sourcecode zu finden. Dazu kann man auch das einfache aber reichaltige Fehlerobjekt Err benutzen. Nochmals: Projekt /c zwingt zu nichts. Wer möchte kann gerne strcmp(...) benutzen. Weitere Fragen beantworte ich gerne!
Moin, Also mich erinnern solche Projekte wie hier eher an sowas: Beim Einschlagen von Naegeln, einfach die Hand, die die Naegel haelt, lokal betaeuben. Dann tut's auch nicht weh, wenn man mal daneben kloppt... Ich bevorzuge einfach mal die Warnings des gcc zu aktivieren und nicht zu ignorieren und ihrer Ursache auf den Grund gehen. Und die auch auf Englisch belassen, dann findet man deutlich mehr dazu im Netz. Dann nochmal ein Lauf mit valgrind und dort eigenartigen Meldungen nachspueren und der Drops ist deutlich nachhaltiger gelutscht, als mit irgendwelchen windigen glibc-Funktionsverschlimmbesserungen. Gruss WK
Günther S. schrieb: > Trotz sorgfältiger Codierung wird es Fehler geben. Fehlermeldungen > wie "Speicherzugriffsfehler (Spe Findest du? Wenn du das Programm im Debugger (gdb) startest findest du solche Fehler (NULL-Pointer-Zugriff) sofort.
Der Debugger hilft erst, wenn der Fehler aufgetreten ist! Ich habe im Projekt /c 317 Stellen mit Str-Tests gefunden. Es geht um das Laufzeitverhalten. Ich sehe als Mathematiker keine Möglichkeit mit Test herauszufinden, unter welchen Bedingungen diese Test schief laufen könnten. Die einfachste Lösung: Alle Tests funktionieren immer. Str NULL ist ja kein Fehler! Jeder Programmierer kann da seine eigene Lösung finden! Wenn es um funktionierende Programme geht bringen solche Diskusionen nicht weiter.
Günther S. schrieb: > Der Debugger hilft erst, wenn der Fehler aufgetreten ist! Wenn Debugging der Vorgang ist, Fehler aus dem Code auszubauen, ist Programmierung der Vorgang die Fehler einzubauen.
Günther S. schrieb: > Ich sehe als Mathematiker keine > Möglichkeit mit Test herauszufinden, unter welchen Bedingungen diese > Test schief laufen könnten. Richtig, das geht grundsätzlich nicht (verwandt mit Halteproblem, Satz von Rice). Günther S. schrieb: > Die einfachste Lösung: Alle Tests funktionieren immer. Str NULL ist ja > kein Fehler! Heißt aber auch, dass du zuvor auftretende Fehler verschleierst - wenn irgendein String eigentlich nie NULL sein sollte, aber doch mal NULL wird, wird dein StrCmp das einfach ignorieren und du wunderst dich warum. Wenn das strcmp aber abstürzt, findest du schnell den Fehler. Wichtiges Konzept: Fehler möglichst früh finden (auch durch Absturz), statt später zu ignorieren. Abstürze können etwas Gutes sein, um Fehler zu finden. Die kann man daher auch gezielt per assert() herbeiführen. Ich würde grundsätzlich versuchen, String-Pointer nie NULL werden zu lassen. Wenn eine Funktion (z.B. strdup()) doch mal NULL zurückgibt, sollte man lieber direkt abbrechen/Programm beenden (z.B. per abort()). Wenn man den NULL-Pointer hier aber "erlaubt" und dann später in einem eigenen StrCmp() ignoriert, hat man erfolgreich den ursprünglichen Fehler verschleiert und findet ihn nicht mehr so leicht, hat aber wahrscheinlich nichts gewonnen, weil der gewünschte String nicht existiert und das Programm nichts sinnvolles mehr machen kann. Ein Programm, das kein sinnvolles Ergebnis mehr abliefern kann, kann man auch abstürzen lassen. Natürlich gibt es auch Situationen wo ein String (oder sonst irgendein Pointer) durchaus mal NULL sein darf. Dann muss man aber überall dort, wo man den Pointer nutzt, eine Überprüfung auf NULL einbauen. Und das gehört eigentlich nicht in Low-Level-Funktionen wie strcmp, sondern in das Modul/Funktion, die den Pointer deklariert. Modernere Sprachen haben Optional- oder Nullable-Typen, mit denen sich explizit Werte/Referenzen deklarieren lassen, die leer sein können - hier muss man immer explizit auf Null prüfen, sonst gibt's Compiler-Fehler. Stringvergleiche akzeptieren dort keine Optional-Typen, d.h. die Prüfung auf "leer" obliegt dem Aufrufer.
Moin, Günther S. schrieb: > Ich habe im Projekt /c 317 Stellen mit Str-Tests gefunden. Und wer hat diese 317 Stellen programmiert? (Und ich bin auf 10 Planeten zum Tode verurteilt. :-)) Komischerweise hab' ich mir mit C schon ein paarmal in den Fuss geschossen und mir sind Daemonen aus der Nase gekommen. Aber noch nie mit strcmp() mit NULL-ptr Aufrufen. Günther S. schrieb: > Str NULL ist ja > kein Fehler! Es ist halt ein Fehler, irgendwelche Funktionen mit NULL ptr aufzurufen, die dafuer nicht gemacht sind. Ich traue den libc Schreibern und Standardisierern mehr als dir. Bei free() ist ja was eingebaut, dass man das mit NULL aufrufen kann und alles ist prima. Die werden schon Gruende haben, sowas nicht ueberall einzubauen. Gruss WK
:
Bearbeitet durch User
Dergute W. schrieb: > Es ist halt ein Fehler, irgendwelche Funktionen mit NULL ptr aufzurufen, > die dafuer nicht gemacht sind. So ist es. Günther S. schrieb: > Ich sehe als Mathematiker Als Mathematiker&Informatiker kann ich sagen: Die ideale Lösung ist es eine Sprache zu nutzen die Nullable/Optional-Typen kennt und strikt prüft wie Rust oder Kotlin; C++ unterstützt das nur so halb mit std::optional, aber Pointer sind weiterhin ungeprüft. Durch diese statische Prüfung umgeht man das Unentscheidbarkeitsproblem, indem man sich vom Compiler dazu zwingen lässt, einfach den Problemraum zu reduzieren. Wenn es C sein muss gibt es keine strikte Compiler-Prüfung, aber man kann das Verhalten manuell nachmachen, indem man wie erwähnt zwischen Pointern unterscheidet die NULL sein dürfen und solche bei denen es "verboten" ist, und für zweitere eben vor dem Zuweisen auf NULL prüft und ggf. terminiert. So verhindert man das unerwartete NULL-Werte zu späteren Fehlern führen und implementiert eine sinnvolle Fehlerbehandlung; vergisst man die Prüfung irgendwo, verhindert das Weglassen der NULL-Prüfung vor strcmp() etc. das Verschleiern von Fehlern und erleichtert die Suche nach dem zuvor gemachten Fehler.
Günther S. schrieb: > Die einfachste Lösung: Alle Tests funktionieren immer. Str NULL ist ja > kein Fehler! Mir wäre dabei unwohl, meine Programmierfehler durch eine "tolerante" Funktion zu kaschieren. Wenn sie nicht mehr zu Tage treten, wie soll ich sie dann beheben? Deine Lösung erschwert für mich die Fehlersuche. Natürlich kann ein gcc mich nicht davor warnen, wenn ich einen NULL-Pointer übergebe, der erst zur Laufzeit gesetzt wird. Dann bin ich aber froh, wenn das Programm zur Laufzeit crasht. Mit einem core dump bzw. durch einen Debugger findet man dann schnell die entsprechende Stelle und den Verursacher. Dann gibt es zwei Möglichkeiten: 1. Der Null-Pointer ist harmlos. Dann rufe ich meine Funktion, die einen gesetzten Pointer != NULL erwartet, nur bedingt auf. Durch diese Codierung teile ich dem geneigten Leser mit: "Achtung, NULL Pointer kann durchaus vorkommen und ist getrennt zu betrachten!". Das kann zum Beispiel ein simples
1 | if (ptr != NULL) |
2 | {
|
3 | int i = strcmp (ptr, "foo"); |
4 | ...
|
5 | }
|
sein. 2. Der Null-Pointer ist fatal und tritt wegen einer Ausnahmesituation auf, z.B. durch einen vorherigen Bug im Programm. Dann ist es nicht sinnvoll, das Programm weiterlaufen zu lassen, weil die Gefahr eines Amoklaufes besteht, der weitere unvorhersehbare Konsequenzen haben kann. Mit Deiner Funktion StrCmp() verwässerst Du die beschriebene Situation Nr. 2 und gefährdest unter Umständen die Sicherheit Deines Systems zur Laufzeit. Mein Fazit: Laufzeitfehler zu ignorieren kann fatale Auswirkungen haben. Es gibt gute Gründe, warum die libc so ist wie sie ist. P.S. Natürlich: die Anwendung der libc ist nicht immer komfortabel und zeitweise wirkt sie recht angestaubt, was der Enwicklung seit 1970 geschuldet ist. Aber deshalb macht diese Tatsache Deine StrCmp-Funktion nicht zu einer besseren Funktion - ganz im Gegenteil.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.