Gast
#3147946
Wenn es wirkich notwendig wäre den String zu terminieren, dann würde doch das hier nicht funktioniere und in eine endlosschleife enden müssen:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
|
Anzeige
|
String terminieren wirklich notwendig?
Gast
#3147946
Wenn es wirkich notwendig wäre den String zu terminieren, dann würde doch das hier nicht funktioniere und in eine endlosschleife enden müssen:
Gast
#3147952
Netter Trollversuch, aber wo siehst du da eine Endlosschleife?
Gast
#3147954
Das Programmverhalten ist undefiniert. Es kann funktionieren, wenn im Speicher zufällig eine hinter deinem Array ist. Oder es kann ein paar tausend weitere Zeichen ausgeben, bis eine 0 im Speicher steht.
Gast
#3147955
Hans schrieb: > Netter Trollversuch, aber wo siehst du da eine Endlosschleife? Im printf. Bei %s versucht doch printf solange auszugeben bis \0 kommt, und das kommt ja nicht vor, also irgendwie sollte es doch die restlichen Speicherzellen (array) durchsuchen, bis es das Betriebssystem abschießt... oder liege ich da falsch?
Gast
#3147959
Fallobst schrieb: > bis eine 0 im Speicher steht. zufällig funktionierts aber immer ohne dass irgendetwas hinterher kommt. Vielleicht braucht das printf ja gar nicht, aber es muss es doch brauchen, denn ein Leerzeichen gehört dann auch zum String, und ich kann mir aber beim besten Willen nicht vorstellen, dass bei 15 mal von 15 Versuchen immer Leerzeichen und \0 im Speicher steht! vorname ist drei zeichen lang, es werden drei minus eins gleich zwei zeichen kopiert. vorname ist mit drei mal null ix null null initialisert. edit: zorry, korrigiere mich: vorname ist eine stackvariable d.h. inhalt unbekannt, evtl. zufällig null.
Gast
#3148009
Lass doch mal das -1 weg.
Gast
#3148024
Frank schrieb: > mir aber beim besten Willen nicht vorstellen, dass bei 15 mal von 15 Doch, weil Windows dir den dem Programm zugewiesenen Speicher mit Nullen füllt. Ein anderes Betriebssystem könnte den Speicher auch m mit 0x12 füllen.
Gast
#3148148
Fallobst schrieb: > Doch, weil Windows dir den dem Programm zugewiesenen Speicher mit Nullen > füllt maximal bei ersten Speicher anfordern, Speicher den man selber freigegeben hat bekommt man auch gefüllt wieder.
Gast
#3148245
Frank schrieb: > zufällig funktionierts aber immer ohne dass irgendetwas hinterher kommt. > Vielleicht braucht das printf ja gar nicht, aber es muss es doch > brauchen, denn ein Leerzeichen gehört dann auch zum String, und ich kann > mir aber beim besten Willen nicht vorstellen, dass bei 15 mal von 15 > Versuchen immer Leerzeichen und \0 im Speicher steht! Meine Güte, ja du hast Recht, alle C-Bücher sind falsch, und man braucht eine 0-Terminierung. Bist du jetzt glücklich?
Gast
#3148246
>Meine Güte, ja du hast Recht, alle C-Bücher sind falsch, und man >braucht eine 0-Terminierung. Bist du jetzt glücklich? Schlechte Laune ? Man könnte es auch anders formulieren: Nicht die Notwendigkeit der Terminierung ist falsch, sondern das ganze Konzept dieser Terminierung, also der Darstellung von Strings, ist grottenfalsch und eine stete Quelle von Exploits in Programmen aller Art.
Gast
#3148261
A. K. schrieb: > Man könnte es auch anders formulieren: Nicht die Notwendigkeit der > Terminierung ist falsch, sondern das ganze Konzept dieser Terminierung ... Was erwartest du von einer Programmiersprache aus den 70er Jahren des vorigen Jahrtausends. ;-) Ganz so mittelalterlich ist sie dann doch nicht. ;-) A. K. schrieb: > sondern das ganze Konzept dieser Terminierung, > also der Darstellung von Strings, ist grottenfalsch Also bräuchtest Du Strings, die ihre Länge mit sich transportieren, was die Verarbeitung, wie z.B. das Anhängen verkomplizieren. Ein strcat wird ohne Umkopieren des Zielstrings nur schwer implementierbar sein. Das Problem ist nicht die Stringrepräsentation, das Problem sind die nach wie vor vorhandenen Stringverarbeitungsfunktionen, die ohne Längenangabe arbeiten, also strcpy, strcat, sprintf etc. Diese Funktionen sollten "verboten" werden und durch ihre Komplemente mit Längenangabe ersetzt werden, also strncpy, strncat, snprintf etc. Mit Disziplin kann man das in den Griff bekommen, nur steht so etwas in all den tollen "Tutorials" nicht drin, die von Anfängern gerne anstelle von ernstgemeinten Büchern zu Hilfe gezogen werden. C ist keine Anfängerprogrammiersprache. Den Anspruch hatte es auch nie.
Gast
#3148340
Rufus Τ. Firefly schrieb: > Also bräuchtest Du Strings, die ihre Länge mit sich transportieren, was > die Verarbeitung, wie z.B. das Anhängen verkomplizieren. Und die hardwarenahe Programmierung wie auf Mikrocontrollern oder in Kerneln schwierig machen. Wenn man "einfache" Strings will, nimmt man C++ oder Java oder... Frank schrieb: > ich kann > mir aber beim besten Willen nicht vorstellen, dass bei 15 mal von 15 > Versuchen immer Leerzeichen und \0 im Speicher steht! Nun, vielleicht ist es in deinem Setup mit diesem Programm, diesem Compiler und diesem Betriebssystem eben so dass tatsächlich immer 0 da steht. Wenn du also niemals irgendetwas (wie zB dein Programm) änderst, könntest du die Terminierung weglassen. Aber dann musst du jedes Mal, wenn du irgend etwas mit Strings programmierst, den Compiler updatest oder gar das Programm auf einen anderen Computer kopierst, genau überprüfen, ob das da immer noch zufällig genau so hinkommt. Einige Programmierer tun das nicht, verlassen sich darauf dass es zufällig immer passt, und das Resultat sind dann Dinge wie die Sicherheitslücken im Adobe PDF-Reader und 900000 anderen Programmen.
Gast
#3148498
Gast
#3148510
Doris schrieb: > strncpy(vorname, vorname2, MAX-1)[MAX-1] = '\0'; Teilnehmer des obfuscated c contest? =-O
Gast
#3151229
Rufus Τ. Firefly schrieb: > Ein strcat wird ohne Umkopieren des Zielstrings nur schwer > implementierbar sein. Na sicher geht das, es ist ja nicht so, dass es nicht schon Sprachen mit Strings mit Laengenangabe gegeben haette. Die Frage ist eigentlich nur, wie viele Bytes man fuer die Laengenangabe reservieren moechte. Da hat es C eben einfacher. Marwin schrieb: > Die Frage ist eigentlich nur, > wie viele Bytes man fuer die Laengenangabe reservieren moechte. Da hat > es C eben einfacher. Dafür ist ein strlen() in C deutlich teurer was die Ausführzeit betrifft als in anderen Sprachen. In Pascal wiederum hatte man damals ein maximum von 255 Bytes für einen String. man könnte auch variabel lange ints nehmen (Ähnlich wie UTF-8 codierte Zeichen. In C ist halt dieses Konzept gewählt worden, mit allen seinen Vor und Nachteilen. Es gibt keinen Königsweg. Frank schrieb: > Wenn es wirkich notwendig wäre den String zu terminieren, dann würde > doch das hier nicht funktioniere und in eine endlosschleife enden > müssen: Prima, damit hast du gezeigt daß du noch nicht viel verstanden hast und besser ein C Buch lesen würdest. Frank schrieb: > Wenn es wirkich notwendig wäre den String zu terminieren, dann würde > doch das hier nicht funktioniere und in eine endlosschleife enden > müssen: Dr. Sommer schrieb: > Frank schrieb: >> ich kann >> mir aber beim besten Willen nicht vorstellen, dass bei 15 mal von 15 >> Versuchen immer Leerzeichen und \0 im Speicher steht! > Nun, vielleicht ist es in deinem Setup mit diesem Programm, diesem > Compiler und diesem Betriebssystem eben so dass tatsächlich immer 0 da > steht. Ich will Euch ja nicht mit Realitäten langweilen, aber der ANSI-Standard für C ist da eindeutig zum Thema strncpy (hab leider nur den Draft hier rumliegen, sry): "7.21.2.4 The strncpy function Synopsis #include <string.h> char *strncpy(char * restrict s1, const char * restrict s2, size_t n); Description The strncpy function copies not more than n characters (characters that follow a null character are not copied) from the array pointed to by s2 to the array pointed to by If copying takes place between objects that overlap, the behavior is undefined. If the array pointed to by s2 is a string that is shorter than n characters, null characters are appended to the copy in the array pointed to by s1, until n characters in all have been written." Quelle: "WG14/N1336 Committee Draft — August 11, 2008 ISO/IEC 9899:201x", Pg 326-327 Beachtet den letzten Absatz. Mit anderen Worten, im Beispiel des TE (zwei Zeichen werden in einen drei Zeichen langen String kopiert) padded strncpy mit '\0'. Schönes Wochenende Grüße Andreas Andreas H. schrieb: > Mit anderen Worten, im Beispiel des TE (zwei Zeichen werden in einen > drei Zeichen langen String kopiert) padded strncpy mit '\0'. Ich würde mal sagen: umgekehrt. Wenn ich mehr Zeichen kopieren will, als der Ausgangsstring hergibt, dann wird der Rest mit Nullen aufgefüllt. Andreas H. schrieb: > Beachtet den letzten Absatz. > > Mit anderen Worten, im Beispiel des TE (zwei Zeichen werden in einen > drei Zeichen langen String kopiert) padded strncpy mit '\0'. Quatsch. MAX-1 erlaubt strncpy() explizit nur das Schreiben von zwei Zeichen (für MAX = 3). Woher soll strncpy() denn auch sonst die Information nehmen, bis wo es padden soll? Ralf G. schrieb: > Ich würde mal sagen: umgekehrt. Wenn ich mehr Zeichen kopieren will, als > der Ausgangsstring hergibt, dann wird der Rest mit Nullen aufgefüllt. Ups, hast recht. Sry 4 te noise ;-) Grüße Andreas Frank schrieb: > Hans schrieb: >> Netter Trollversuch, aber wo siehst du da eine Endlosschleife? > > Im printf. Bei %s versucht doch printf solange auszugeben bis \0 kommt, Ja. > und das kommt ja nicht vor Das weißt du nicht, das vermutest du nur. Ich tippe mal darauf, daß deine Laufzeitumgebung das char Array vorname mit \0 initialisiert, was es zwar darf aber nicht zwingend muß. Und weil du mit strncpy() nur die ersten beiden Zeichen überschreibst, hast du am Ende dann doch wieder einen 0-terminierten String. Und deswegen läuft printf() dann auch nicht Amok. Das blöde ist, daß dir der C-Standard dieses Verhalten nicht garantiert. Das kann also mit einem anderen Compiler oder auf einer anderen Plattform in die Hose gehen. Dein Code ist also auf die bösest mögliche Art fehlerhaft und ich hoffe ernsthaft, daß du niemals solchen Code absichtlich (v)erbrichst. XL
Gast
#3151707
Andreas H. schrieb: > Ich will Euch ja nicht mit Realitäten langweilen, aber der ANSI-Standard > für C ist da eindeutig zum Thema strncpy > The strncpy function copies not more than n characters Tolle Diskussion, aber eigentlich gibt es nur eine Antwort - Andreas H. hat Recht. A. K. schrieb: > Man könnte es auch anders formulieren: Nicht die Notwendigkeit der > Terminierung ist falsch, sondern das ganze Konzept dieser Terminierung, > also der Darstellung von Strings, ist grottenfalsch Das ist zunächst mal Ansichtssache. Von den beiden offensichtlichen Arten, Strings im Speicher zu repräsentieren, hat C sich für eine Ende-Markierung entschieden (und Pascal für ein Längenbyte). Jede der beiden Varianten hat Vor- und Nachteile. Ach ja, Pascal ist tot. C nicht so. > und eine stete Quelle von Exploits in Programmen aller Art. Die sind aber weniger der Programmiersprache anzulasten als dem Programmierer^H^Hlegastheniker. Wenn der Handwerker mit einem Werkzeug schlechte Resultate erzielt, ist nicht automatisch das Werkzeug Schuld. Und falls ein Programmierer zu faul sein sollte, sich immer um die Terminierung zu kümmern, dann hindert ihn ja keiner daran, seine eigene, bequemere String-Repräsentation zu verwenden und nur dort wo es nötig ist (im wesentlichen für calls in die stdlib) auf C-Strings zu wechseln. Huch, ist ja schon passiert. C++ und std::string anyone? XL Axel Schwenke schrieb: > A. K. schrieb: >> Man könnte es auch anders formulieren: Nicht die Notwendigkeit der >> Terminierung ist falsch, sondern das ganze Konzept dieser Terminierung, >> also der Darstellung von Strings, ist grottenfalsch > > Das ist zunächst mal Ansichtssache. Von den beiden offensichtlichen > Arten, Strings im Speicher zu repräsentieren, hat C sich für eine > Ende-Markierung entschieden (und Pascal für ein Längenbyte). Jede der > beiden Varianten hat Vor- und Nachteile. Ach ja, Pascal ist tot. > C nicht so. Auf der anderen Seite scheint es mir aber, als ob die Pascal-Variante in anderen Sprachen deutlich häufiger zu finden ist - allerdings meist hinter einen Interface versteckt, so daß man es als Programmierer gar nicht sieht. >> und eine stete Quelle von Exploits in Programmen aller Art. > > Die sind aber weniger der Programmiersprache anzulasten als dem > Programmierer^H^Hlegastheniker. Wenn der Handwerker mit einem Werkzeug > schlechte Resultate erzielt, ist nicht automatisch das Werkzeug Schuld. So sehen es aber die meisten heutzutage. Deshalb ist ja auch der Mikrowellen-Hersteller schuld am Ableben des Schoßhündchens, wenn der Benutzer so dämlich ist, es darin trocknen zu wollen. Und McDonad's ist schuld, wenn sich jemand verbrüht, da er ja nicht ahnen kann, daß sein gerade bestellter Kaffee heiß ist. Und wenn jemand sich nicht um Array-Längen und korrekt terminierte Strings kümmert, ist die Programmiersprache schuld. Fakt ist: Wenn man ein technisches Produkt auf den Markt bringt und nicht schuld am Zusammenbrechen der Welt wie wir sich kennenen sein will, muß man alles unter der Annahme entwickeln, daß der Benutzer zu blöd zum Sch* ist.
Gast
#3152051
Fakt ist, man braucht eine Sprache, die keine versteckten Längenbytes bei Strings&Arrays hat, sondern nur ganz dumm genau das tut was man schreibt; gerade im Embedded-Bereich ist das sehr wichtig. Diese Sprache heißt eben C. Das wird in C auch niemals geändert, denn dann wäre C nicht mehr für so etwas geeignet, und man bräuchte eine neue Sprache... Wenn man automatische Längenverwaltung in Strings haben möchte, sollte man eine andere Sprache verwenden. Werkzeug-Analogie: Wenn man die Kraft beim Schrauben nicht von Hand aufbringen will, bastelt man keinen Motor an den Handbohrer, sondern kauft sich eine richtige Bohrmaschine mit Motor... Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|