Thread View: de.comp.lang.c++
16 messages
16 total messages
Started by Dietmar Kuehl
Wed, 28 Feb 1996 23:46
Vergleich 'strcmp()' 'string == string' (Was: Q: gcc 2.7.1: Aufruf einer Konstruktormethode aus einer anderen)
Author: Dietmar Kuehl
Date: Wed, 28 Feb 1996 23:46
Date: Wed, 28 Feb 1996 23:46
93 lines
5025 bytes
5025 bytes
Hi,
vorne weg: Ich habe einfach mal 'strcmp()' und 'bool operator==(string
const &, string const &)' verglichen (Code und genaue Ergebnisse kann
ich auch posten, ist aber nicht so furchtbar interessant; die
relevanten Ergebnisse erwaehne ich hier ungefaehr). Ich kann nicht
argumentieren, dass 'operator==()' schneller waere: das ist nicht der
Fall, auch dann nicht, wenn ich den Vergleich "fair" mache (der
Vergleich der vorgeschlagen wurde ist naemlich, IMHO, nicht fair). Es
bleibt beim gcc-2.7.2 mit '-O2' ein Faktor von ungefaehr zwei, den ich,
bei geeigneter Wahl der Strings, langsamer bin. Bei dem vorgeschlagenen
Vergleich gibt es da schon einen deutlich groesseren Faktor in der
Groessenordnung von ~30.
Ullrich von Bassewitz (uz@wuschel.ibb.schwaben.com) wrote:
: Da class string den String prinzipiell immer auf den Heap packt ist wohl
: klar, woher der Performance Unterschied kommt. Stell Dir folgende Funktion
: vor:
: int StrCmp1 (const string& lhs, const string& rhs);
: // Compare two strings
: und
: int StrCmp2 (const char* lhs, const char* rhs);
: // Compare two string
: Wenn Du einen Aufuf hast, wie:
: if (StrCmpX ("foo", "bar") == 0) { /* ... */ }
So einen Aufruf habe ich aber garnicht! Da kommen ja 'char const*' vor
:-) Ich habe aber immer nur 'string's. Mit anderen Worten: Der Vergleich
ist meiner Meinung nach nicht fair. Wenn dann ist ein Aufruf
wie
string s1("foo");
string s2("bar");
// hier beginnt die Zeitmessung
if (StrCmpX(s1, s2) == 0) { }
angesagt. Sicher muss ich meine 'string's irgendwann konstruieren, aber
entweder ist der Aufwand zu vernachlaessigen (fuer die Literale: bevor
sich was bei der Zeitmessung tut, muss ich schon fleissig viele
'string's anlegen...) oder sie muessen auch als 'char*' angelegt
werden, was ungefaehr den selben Aufwand hat.
: dann werden das eine mal einfach zwei Zeiger uebergeben, das andere Mal
: werden zwei Objekte konstruiert (dazu wird Speicher auf dem Heap belegt und
: der String dort rein kopiert), nach dem Aufruf wird der belegte Speicher
: wieder freigegeben.
Ja, sicher. Wie gesagt, das ist, IMHO, kein vernuenftiger Vergleich.
Aber, und das habe ich auch schon gesagt: Auch wenn man die 'string's
vorher anlegt, bleibt es langsamer. Naja, bei langen Strings ist
'string' schneller (lang == > 50)
: Ich habe nicht gesagt, dass die niedrigere Performance tatsaechlich eine
: Rolle spielt, das tut sie in den meisten Faellen nicht (auch wenn 99% aller
: Programmierer fest davon ueberzeugt sind, dass genau ihr Programm mit -O9
: uebersetzt werden muss, und dass Bounds Checking bei Arrays des Teufels ist,
: weil es zwar Bugs abfaengt, aber die Performance drueckt).
Zu dem Thema habe ich sowieso schon immer eine andere Meinung: mein
Code ist zwar schon teilweise optimiert (wo es noetig war oder wo ich
Zeit zum Optimieren hatte), aber sonst gehoert er zu den 80% des Code,
der sowieso nicht in den inneren Schleifen liegt. Seit neustem, genauer
seitdem ich intensiv mit Templates arbeite, lohnt sich allerdings auf
jeden Fall -O zu verwenden, da damit offensichtlich eine ganze Menge
'inline' gemacht wird, was die Abstraktion, die ich mit mir
"rumschleppe", billiger (bzw. kostenlos) macht. Ansonsten bin ich eher
auf der Linie von James Kanze (von dem, und vor allem seinem
Programmierstil, halte ich eine ganze Menge...): Er meint, man soll
alle Tests (z.B. bounds checking) im endgueltigen Code lassen. Der
groesste Teil ist sowieso nicht teuer (80-20 Regel) und den Rest kann
man sich leisten. Der Vorteil: WENN ein Fehler auftritt, dann hat man
wenigstens einen Hinweis, wo der herkam. Im Testing ist er ja
offensichtlich nicht aufgetreten, also ist er schwer zu reproduzieren.
...aber man muss ihn beheben.
: Das Problem ist nicht die Uebergabe, sondern dass strings so implementiert
: sind, dass die Daten auf dem Heap liegen. Das kann in bestimmten
: Konstellationen (wie die oben) zu einer recht lausigen Performance fuehren.
Ja. Allerdings muess eine solche Konstellation auch auftreten koennen.
Wenn man wirklich und fuer alles 'string' verwendet, tut sie das aber
nicht. Es ist schon richtig: halbherzig 'string' zu verwenden ist zu
teuer...
PS: knapp unter 100. Ich muss mich kuerzer fassen...
--
dietmar.kuehl@uni-konstanz.de
http://www.informatik.uni-konstanz.de/~kuehl
I am a realistic optimist - that's why I appear to be slightly pessimistic
Re: Vergleich 'strcmp()' 'string == string' (Was: Q: gcc 2.7.1: Aufruf einer Konstruktormethode aus einer anderen)
Author: Ullrich von Bassewitz
Date: Thu, 29 Feb 1996 07:36
Date: Thu, 29 Feb 1996 07:36
43 lines
2340 bytes
2340 bytes
Dietmar Kuehl (kuehl@uzwil.informatik.uni-konstanz.de) wrote:
> Bei dem vorgeschlagenen
> Vergleich gibt es da schon einen deutlich groesseren Faktor in der
> Groessenordnung von ~30.
Der in einer "echten" Applikation nochmals um den Faktor 2-3 ansteigt, weil
dann der Heap fragmentiert ist...
> Ja, sicher. Wie gesagt, das ist, IMHO, kein vernuenftiger Vergleich.
Das ist schon ein vernuenftiger Vergleich, wenn man bedenkt, warum ich das
gesagt habe: Es ging um eine generelle Kritik an char* aufgrund von ein
paar Zeilen Code. Keiner von uns wusste, warum dieser Code genau so
aussieht, und ich habe lediglich Szenarios gebildet, warum dieser Code so
aussehen kann. Meine Szenarios sind aber im Rahmen von realen Aufgaben-
stellungen durchaus denkbar, Dein Argument
> Wenn man wirklich und fuer alles 'string' verwendet, tut sie das aber
> nicht.
ist falsch, ich kann Dir auf Anhieb ein Dutzend Moeglichkeiten nennen, warum
Du trotzdem char*'s kriegst (ein Beispiel habe ich bereits genannt [Shared
Memory], das zweite sind z.B. Betriebssystemfunktionen, die char*
zurueckliefern, auch hier musst Du jedesmal(!) einen string konstruieren).
[Checks im Produktionscode]
Das mache ich auch (bereits seit ca. 5 Jahren). Der Geschwindigkeits-
unterschied spielt normalerweise keine Rolle, und wenn doch, dann lohnt es
sich normalerweise eher, einen schnelleren Rechner einzusetzen (wo moeglich),
als Checks zu disablen. Die paar Mark, die man fuer ein schnelleres System
ausgibt sind schnell wieder weg, wenn man irgendwo einen Fehler hat, bei dem
man noch nicht mal andeutungsweise sagen kann, wo er herkommt, weil man
saemtliche Checks disabled hat.
Insofern sind wir da durchaus einer Meinung :-)
Gruss
Uz
--
Ullrich von Bassewitz uz@ibb.schwaben.com
Re: Vergleich 'strcmp()' 'string == string' (Was: Q: gcc 2.7.1: Aufruf einer Konstruktormethode aus einer anderen)
Author: Bernd Eggink
Date: Thu, 29 Feb 1996 12:01
Date: Thu, 29 Feb 1996 12:01
47 lines
2752 bytes
2752 bytes
Dietmar Kuehl (kuehl@uzwil.informatik.uni-konstanz.de) wrote: [ ... ] > Ansonsten bin ich eher > auf der Linie von James Kanze (von dem, und vor allem seinem > Programmierstil, halte ich eine ganze Menge...): Er meint, man soll > alle Tests (z.B. bounds checking) im endgueltigen Code lassen. Der > groesste Teil ist sowieso nicht teuer (80-20 Regel) und den Rest kann > man sich leisten. Der Vorteil: WENN ein Fehler auftritt, dann hat man > wenigstens einen Hinweis, wo der herkam. Im Testing ist er ja > offensichtlich nicht aufgetreten, also ist er schwer zu reproduzieren. > ...aber man muss ihn beheben. [ ... ] Gute Idee. Fragt sich nur, wie man dann z.B. die STL benutzen soll, in der NULL Checks gemacht werden und die einem eine breite Palette wunderbarer neuer Moeglichkeiten eroeffnet, sich selbst ein Bein zu stellen... Ueberhaupt, dass mit C++ sicherere und leichter maintenierbare Programme quasi von selbst entstuenden, scheint mir das schlimmste von allen Vorurteilen ueber die Sprache zu sein. Irgendein grosser Softwarehersteller, ich habe vergessen, wer's war, soll ja sogar die extreme Fehlerhaftigkeit seine Software damit entschuldigt haben, dass sie in C++ geschrieben sei! Insofern neige ich - kleiner Nachtrag zu der programmierphilosophischen Diskussion - auch eher zu einem pragmatischen Standpunkt: Wer mit rohen Pointern gut umgehen kann, soll dabei bleiben. Wer damit laufende Meter Probleme hat, wird sich schon aufgrund seines Leidensdrucks etwas anderes ueberlegen. Man *muss* nicht alles verpacken. Und was den Stil in dem bewussten Thread betrifft (den ich mit grossem Vergnuegen gelesen habe): Das Hauptproblem scheint mir die deutsche Eigenheit zu sein, aus persoenli- chen Vorlieben gleich kategorische Imperative zu machen. Du MUSST dies tun! Du MUSST jenes lassen! Dies ist GUT! Alles andere ist BOESE! Aber es gibt keine allgemeingueltigen, einfachen Wahrheiten. Zum Glueck, denn dann waere die Welt verdammt langweilig. Gruss Bernd Eggink -- +----------------------------------+ | Bernd Eggink | | Rechenzentrum Uni Hamburg | | admin@rzaix13.rrz.uni-hamburg.de | +----------------------------------+
Re: Vergleich 'strcmp()' 'string == string' (Was: Q: gcc 2.7.1: Aufruf einer Konstruktormethode aus einer anderen)
Author: Joachim Zobel
Date: Sun, 03 Mar 1996 00:36
Date: Sun, 03 Mar 1996 00:36
41 lines
2193 bytes
2193 bytes
Hi, ich hab' leider das ursprßngliche Posting nicht mitgekriegt, ging es um eine spezielle Stringklasse oder um Stringklassen im allgemeinen? uz@wuschel.ibb.schwaben.com (Ullrich von Bassewitz) wrote: >Dietmar Kuehl (kuehl@uzwil.informatik.uni-konstanz.de) wrote: >> Bei dem vorgeschlagenen >> Vergleich gibt es da schon einen deutlich groesseren Faktor in der >> Groessenordnung von ~30. >Der in einer "echten" Applikation nochmals um den Faktor 2-3 ansteigt, weil >dann der Heap fragmentiert ist... Falls man tatsächlich ein Performanceproblem hat, liegt es fßr Strings nahe, eine eigene Allocationsf'n zu schreiben, die einen Pool von Bloecken von z.B. 64 Byte Länge unterhält, aus dem alle 'kleinen' Allokationen genommen werden. War die fragliche Stringklasse irgendwie optimiert? [...] >> Wenn man wirklich und fuer alles 'string' verwendet, tut sie das aber >> nicht. >ist falsch, ich kann Dir auf Anhieb ein Dutzend Moeglichkeiten nennen, warum >Du trotzdem char*'s kriegst (ein Beispiel habe ich bereits genannt [Shared >Memory], das zweite sind z.B. Betriebssystemfunktionen, die char* >zurueckliefern, auch hier musst Du jedesmal(!) einen string konstruieren). Ich habe bisher char * verwendet und ueberlege im Moment, fßr den Uebergang eine Stringklasse einzufuehren, die nicht alloziiert, sondern nur die Länge prueft, und ansonsten den im _ctor uebergebenen Speicher verwendet. So eine Art Wrapper fuer strncpy. Jochim "Man faengt Forellen mit der Hand, indem man zuerst ihr Vertrauen gewinnt und es dann missbraucht." Robert A. Heinlein
Re: Vergleich 'strcmp()' 'string == string' (Was: Q: gcc 2.7.1: Aufruf einer Konstruktormethode aus einer anderen)
Author: Joachim Zobel
Date: Sun, 03 Mar 1996 00:41
Date: Sun, 03 Mar 1996 00:41
41 lines
2193 bytes
2193 bytes
Hi, ich hab' leider das ursprßngliche Posting nicht mitgekriegt, ging es um eine spezielle Stringklasse oder um Stringklassen im allgemeinen? uz@wuschel.ibb.schwaben.com (Ullrich von Bassewitz) wrote: >Dietmar Kuehl (kuehl@uzwil.informatik.uni-konstanz.de) wrote: >> Bei dem vorgeschlagenen >> Vergleich gibt es da schon einen deutlich groesseren Faktor in der >> Groessenordnung von ~30. >Der in einer "echten" Applikation nochmals um den Faktor 2-3 ansteigt, weil >dann der Heap fragmentiert ist... Falls man tatsächlich ein Performanceproblem hat, liegt es fßr Strings nahe, eine eigene Allocationsf'n zu schreiben, die einen Pool von Bloecken von z.B. 64 Byte Länge unterhält, aus dem alle 'kleinen' Allokationen genommen werden. War die fragliche Stringklasse irgendwie optimiert? [...] >> Wenn man wirklich und fuer alles 'string' verwendet, tut sie das aber >> nicht. >ist falsch, ich kann Dir auf Anhieb ein Dutzend Moeglichkeiten nennen, warum >Du trotzdem char*'s kriegst (ein Beispiel habe ich bereits genannt [Shared >Memory], das zweite sind z.B. Betriebssystemfunktionen, die char* >zurueckliefern, auch hier musst Du jedesmal(!) einen string konstruieren). Ich habe bisher char * verwendet und ueberlege im Moment, fßr den Uebergang eine Stringklasse einzufuehren, die nicht alloziiert, sondern nur die Länge prueft, und ansonsten den im _ctor uebergebenen Speicher verwendet. So eine Art Wrapper fuer strncpy. Jochim "Man faengt Forellen mit der Hand, indem man zuerst ihr Vertrauen gewinnt und es dann missbraucht." Robert A. Heinlein
Re: Vergleich 'strcmp()' 'string == string' (Was: Q: gcc 2.7.1: Aufruf einer Konstruktormethode aus einer anderen)
Author: Dietmar Kuehl
Date: Sun, 03 Mar 1996 20:40
Date: Sun, 03 Mar 1996 20:40
70 lines
4317 bytes
4317 bytes
Hi, Joachim Zobel (a2597420@athena.rrz.uni-koeln.de) wrote: : ich hab' leider das ursprßngliche Posting nicht mitgekriegt, ging es : um eine spezielle Stringklasse oder um Stringklassen im allgemeinen? Der Anfang der (recht ergiebigen) Diskussion war in dem Thread ueber den Aufruf eine Konstruktormethod und begann mit meiner sehr verallgemeinerten Behauptung, dass die Deklaration 'char *string' "GANZ SCHLECHT" ist... Um den Thread, der sich daraufhin um mehrere Aspekte drehte (Art und Weise von Kritik an andere Leute Code; "to pointer or not to pointer"; 'string' und die Kosten von Abstraktion) ein wenig handhabbarer zu machen, habe ich ihn einfach mal aufgeteilt... Es ging an dieser Stelle ganz direkt um einen Vergleich zwischen 'char*' und der Standardklasse 'string' i.e. 'basic_string<char, string_char_traits<char>, allocator>' (siehe DWP). Den Vergleich habe ich mit der (fast) Standard konformen Implementation aus libg++-2.7.1 mit gcc-2.7.2 auf einer Sparc 1000 mit Solaris 2.4 gemacht. : Falls man tatsächlich ein Performanceproblem hat, liegt es fßr Strings : nahe, eine eigene Allocationsf'n zu schreiben, die einen Pool von : Bloecken von z.B. 64 Byte Länge unterhält, aus dem alle 'kleinen' : Allokationen genommen werden. Jau, das kann man in einer Standard konformen Implementation z.B. in den Allocator packen (in diesem Punkt libg++ ganau vom Standard ab, i.e. es gibt keine Allocator). Allerdings ging es nicht um ein Performanceproblem, sondern um einen vollkommen naiven, unrealistischen Test (einfach ein paar tausend mal zwei Strings miteinander vergleichen, wobei lediglich sichergestellt wurde, dass der Vergleich nicht wegoptimiert wird), der die Kosten der Abstraktion untersuchen sollte (es gab da eine Behauptung, dass 'string' um Klassen langsamer sei, was, je nachdem, wie man es sieht, stimmt bzw. nicht stimmt...). : War die fragliche Stringklasse irgendwie optimiert? Keine Ahnung... 'bastring.h' halt. Gibt es z.B. von Musser's ftp site oder in der libg++. : >> Wenn man wirklich und fuer alles 'string' verwendet, tut sie das aber : >> nicht. : >ist falsch, ich kann Dir auf Anhieb ein Dutzend Moeglichkeiten nennen, warum : >Du trotzdem char*'s kriegst (ein Beispiel habe ich bereits genannt [Shared : >Memory], das zweite sind z.B. Betriebssystemfunktionen, die char* : >zurueckliefern, auch hier musst Du jedesmal(!) einen string konstruieren). : Ich habe bisher char * verwendet und ueberlege im Moment, fßr den : Uebergang eine Stringklasse einzufuehren, die nicht alloziiert, : sondern nur die Länge prueft, und ansonsten den im _ctor uebergebenen : Speicher verwendet. So eine Art Wrapper fuer strncpy. Ich denke, es ist fast immer sinnvoll, eine Stringklasse zu verwenden: Man kann zunaechst eine triviale Klasse implementieren, die man "smarter" macht, wenn es sich anbietet (selbstverstaendlich aendert man dabei das Interface nicht...). D.h. man kann z.B. "under the hood" sowas wie "lazy evaluation" machen. Man koennte, auch in bei der Implementation von 'basic_string' von "lazy evaluation" gebrauch machen: Man "opfert" halt ein bischen Speicher fuer Verwaltung der "lazy evaluation" (z.B. um zu speichern, ob der String derzeit ge'share't wird, ob man ihn freigeben muss etc.), z.B. einen 'int' und einen zusaetzlichen Pointer. Dafuer reduziert man die Anzahl der Allokationen, tatsaechlich ausgefuehrten Kopien etc. (Siehe etwas Scott Meyers' "More Effective C++"; Item weiss ich gerade nicht...). -- dietmar.kuehl@uni-konstanz.de http://www.informatik.uni-konstanz.de/~kuehl I am a realistic optimist - that's why I appear to be slightly pessimistic
Re: Vergleich 'strcmp()' 'string == string' (Was: Q: gcc 2.7.1: Aufruf einer Konstruktormethode aus einer anderen)
Author: Bernd Eggink
Date: Mon, 04 Mar 1996 10:47
Date: Mon, 04 Mar 1996 10:47
25 lines
1455 bytes
1455 bytes
Joachim Zobel (a2597420@athena.rrz.uni-koeln.de) wrote: [...] > Ich habe bisher char * verwendet und ueberlege im Moment, fßr den > Uebergang eine Stringklasse einzufuehren, die nicht alloziiert, > sondern nur die Länge prueft, und ansonsten den im _ctor uebergebenen > Speicher verwendet. So eine Art Wrapper fuer strncpy. Tu's nicht. Jedenfalls nicht, wenn der im ctor uebergebene Speicher ein Stringliteral "blabla..." sein kann, denn in ein solches sollte man keinesfalls hineinschreiben. Die Wirkung ist undefiniert. Es steht dem Compiler z.B. frei, solche Literale in einem schreibgeschuetzten Speicherbreich unterzubringen. Gruss Bernd Eggink -- +----------------------------------+ | Bernd Eggink | | Rechenzentrum Uni Hamburg | | admin@rzaix13.rrz.uni-hamburg.de | +----------------------------------+
Argghh! String-Literals nicht const! (War:Vergleich 'strcmp()' ...)
Author: Joachim Zobel
Date: Mon, 04 Mar 1996 12:52
Date: Mon, 04 Mar 1996 12:52
33 lines
1959 bytes
1959 bytes
admin@rzaix13.uni-hamburg.de (Bernd Eggink) wrote: >Joachim Zobel (a2597420@athena.rrz.uni-koeln.de) wrote: >[...] >> Ich habe bisher char * verwendet und ueberlege im Moment, fßr den >> Uebergang eine Stringklasse einzufuehren, die nicht alloziiert, >> sondern nur die Länge prueft, und ansonsten den im _ctor uebergebenen >> Speicher verwendet. So eine Art Wrapper fuer strncpy. >Tu's nicht. Jedenfalls nicht, wenn der im ctor uebergebene Speicher >ein Stringliteral "blabla..." sein kann, denn in ein solches sollte >man keinesfalls hineinschreiben. Die Wirkung ist undefiniert. Es steht >dem Compiler z.B. frei, solche Literale in einem schreibgeschuetzten >Speicherbreich unterzubringen. Danke. War mir noch nicht aufgefallen. Scheint mir eine ziemliche Sauerei zu sein. Das ARM (2.5.4) sagt: String literals are of type char[] and not const char[] for compatibility with Classic C where early software took advantage of literals beeing distinct and modifiable. Das heisst: Man hat den Standard so gemacht, das alter Code zwar noch compiliert, aber undefiniertes Verhalten hat, anstatt den Compiler die entsprechenden Stellen anzeigen zu lassen. Was sollte das? Joachim "... ein Geschlecht erfinderischer Zwerge, die fuer alles gemietet werden koennen." - Bertolt Brecht - Das Leben des Gallilei
Re: Argghh! String-Literals nicht const! (War:Vergleich 'strcmp()' ...)
Author: Frank Thilo
Date: Mon, 04 Mar 1996 21:43
Date: Mon, 04 Mar 1996 21:43
35 lines
2060 bytes
2060 bytes
a2597420@athena.rrz.uni-koeln.de (Joachim Zobel) wrote:
>Scheint mir eine ziemliche Sauerei zu sein. Das ARM (2.5.4) sagt:
>
>String literals are of type char[] and not const char[] for
>compatibility with Classic C where early software took advantage of
>literals beeing distinct and modifiable.
>
>Das heisst: Man hat den Standard so gemacht, das alter Code zwar noch
>compiliert, aber undefiniertes Verhalten hat, anstatt den Compiler die
>entsprechenden Stellen anzeigen zu lassen. Was sollte das?
Nun, die Begruendung erscheint mir auch etwas fragwuerdig. Meienr
Meinung nach ist der Grund eher der, dass alter Code halt ohne
Verwendung von 'const' geschrieben wurde und nun nicht mehr
compilierbar waere:
void f(char *);
...
f("test");
Dies gaebe eine Fehlermeldung, wenn Stringliterale vom Typ 'const char *'
waeren. Man muesste also in alle alten Quellcodes explizite casts
hineinschreiben.
Wenn ich mich nicht taeusche (lasse mich gerne korrigieren), werden in
ANSI-C solch implizite casts von 'const char *' auf 'char *'
durchgefuehrt, so dass natuerlich auch hier Probleme beim Umstieg auf
C++ auftreten. Nur ist der Fall mit den Stringkonstanten wohl einfach
zu haeufig.
--
Frank Thilo - thilo@unix-ag.uni-siegen.de - PGP key available
IRC: Chestal - http://www.unix-ag.uni-siegen.de/~thilo/
Re: Argghh! String-Literals nicht const! (War:Vergleich 'strcmp()' ...)
Author: Dietmar Kuehl
Date: Mon, 04 Mar 1996 22:52
Date: Mon, 04 Mar 1996 22:52
40 lines
3048 bytes
3048 bytes
Hi, Joachim Zobel (a2597420@athena.rrz.uni-koeln.de) wrote: : Das heisst: Man hat den Standard so gemacht, das alter Code zwar noch : compiliert, aber undefiniertes Verhalten hat, anstatt den Compiler die : entsprechenden Stellen anzeigen zu lassen. Was sollte das? Nun, der Code kann sich an Stellen, wo man nach Standard "undefined behavior" hat, wohldefiniert verhalten. Allerdings ist das nicht portable und haengt von der Implementation ab. z.B. koennte ein Compiler definieren: "String-Literale werden im Datensegement angelegt und sind modifizierbar". Darauf kann man sich dann bei dem spezifischen Compiler verlassen und z.B. alten Code compilieren. Ein anderer Compiler kann allerdings definieren: "String-Literale werden im Text-Segment angelegt und es gibt eine allgemeine Schutzverletzung, wenn sie modifiziert werden". Beide Implementationen sind Standard konform. Im uebrigen koennen Compiler natuerlich Warnings ausgeben, wenn sie auf eine Stelle stossen, wo ein String-Literal einem 'char*' anstatt einem 'char const *' zugewiesen wird. Fehler duerfen sie da allerdings nicht ausspucken, zumindest dann nicht, wenn sie im ISO C++ konformen Modus laufen: Bei Compilern gibt es oft eine Option, mit der man Erweiterungen/Einschraenkungen anschalten kann. Ich wuerde z.B. bei einer Zuweisung eine String-Literals auf einen 'char*' einen Fehler auswerfen lassen. Aber ich habe da eh nochmehr Einschraenkungen. Die passende Option wuerde vermutlich '-sucks' heissen und nur von Managern zur Ueberpruefung ihrer Leute verwendet werden (... und natuerlich von mir: Ich weiss, dass ich mich vor mir schuetzen muss!). Leider sind non-const string literals kein 'deprecated feature'! D.h. es wird auch in Zukunft nicht geaendert werden (da sind wohl doch zuviele C-Hacker im Kommittee). Was das soll, weiss ich allerdigs wirklich nicht mehr: Jemand der jetzt noch String-Literale aendert gehoert eigentlich vom Programmieren ferngehalten (bestimmt gibt es auch noch Leute, die davon ueberzeugt sind, dass es die EINZIG moegliche und richtige Loesung fuer irgendein Problem ist, das in Wirklichkeit viel besser portable geloest werden kann, dafuer allerdings den Code 0.001% langsamer macht). -- dietmar.kuehl@uni-konstanz.de http://www.informatik.uni-konstanz.de/~kuehl I am a realistic optimist - that's why I appear to be slightly pessimistic
Re: Argghh! String-Literals nicht const! (War:Vergleich 'strcmp()' ...)
Author: Oliver Rebach
Date: Tue, 05 Mar 1996 07:39
Date: Tue, 05 Mar 1996 07:39
28 lines
2004 bytes
2004 bytes
Moin Dietmar, In article <4hfs7p$d8r@news.BelWue.DE>, kuehl@uzwil.informatik.uni-konstanz.de (Dietmar Kuehl) writes: |> |> Leider sind non-const string literals kein 'deprecated feature'! D.h. |> es wird auch in Zukunft nicht geaendert werden (da sind wohl doch |> zuviele C-Hacker im Kommittee). Was das soll, weiss ich allerdigs |> wirklich nicht mehr: Jemand der jetzt noch String-Literale aendert |> gehoert eigentlich vom Programmieren ferngehalten (bestimmt gibt es |> auch noch Leute, die davon ueberzeugt sind, dass es die EINZIG |> moegliche und richtige Loesung fuer irgendein Problem ist, das in |> Wirklichkeit viel besser portable geloest werden kann, dafuer |> allerdings den Code 0.001% langsamer macht). Na ja, spaetestens wenn diese "Meisterprogrammierer" versuchen ihren [C|K]o[de|t] zu einer Shared Library zu linken oder im ein ROM zu brennen ist ja wohl Schluss mit dem Aendern von Literalen. Ich lobe mir den gcc, der laesst als default bei solchen Sauereien einen core werfen, und tschuess. Oliver -- O. Rebach <Oliver.Rebach@UniBw-Hamburg.DE> /|\ /|\ Universitaet der Bundeswehr Hamburg FB Maschinenbau / | \/ | Fachgebiet Maschinenelemente und Getriebetchnik |--| | ~| - CAD - Labor - | | /
Re: Vergleich 'strcmp()' 'string == string' (Was: Q: gcc 2.7.1: Aufruf einer Konstruktormethode aus einer anderen)
Author: Nico Josuttis
Date: Tue, 05 Mar 1996 15:57
Date: Tue, 05 Mar 1996 15:57
36 lines
2190 bytes
2190 bytes
Sorry, aber ich moechte mal kurz einschreiten, habe aber nicht alle
Mails dazu gelesen. Deshalb ein paar Fakten, die (sorry)
evtl. schon jemand gepostet hat:
1) Der Standard umfasst in der Bibliothek einen String.
Der kann natuerlich von und nach char* gewandelt werden
und auch Operationen mit char* durchfuehren.
Insofern verstehe ich die Diskussion mit char* nicht ganz.
Wenn etwas char* ist beziehe ich es mit ein.
Insgesamt ist doch aber wohl die Verwendung von + statt strcat()
und == statt strcmp() weniger fehleranfaellig und somit vorzuziehen.
2) Die Sache ist natuerlich eine Ebene hoeher/abstrakter und
deshalb mitunter langsamer.
ABER NICHT UNBEDING/IMMER:
Typische/gute kommerzielle String-Klassen kopieren String
z.B. nicht sondern verwalten einfach zwei Verweise auf
die gleiche Zeichenfolge.
Man beachte, dass String relativ selten geaendert dagegen oft
kopiert und zugeweisen werden.
Damit sind wir evtl. sogar SCHNELLER als mit einfachen
char* Implementierungen.
Das ganze steht u.a. im Stroustrup und an vielen anderen
Stellen und nennt sich das "reference counting idiom" oder
``handle/body class idiom'' oder ``Counted Body Pattern''.
Generell sollte, denke ich deshalb string verwendet werden
und mit char* zusammen verwendet werden, wenn es aufgrund
von Schnittstellen nach aussen notwendig ist.
Es lohnt sich.
--
Nico address: BREDEX GmbH, Nicolai Josuttis
email: nico@bredex.de Fallersleber-Tor-Wall 23
phone: +49 531 24330-0 D-38100 Braunschweig
fax: +49 531 24330-99 Germany
Re: Argghh! String-Literals nicht const! (War:Vergleich 'strcmp()' ...)
Author: Dietmar Kuehl
Date: Tue, 05 Mar 1996 16:44
Date: Tue, 05 Mar 1996 16:44
21 lines
1808 bytes
1808 bytes
Hi, Oliver Rebach (m_rebach@balu.unibw-hamburg.de) wrote: : Ich lobe : mir den gcc, der laesst als default bei solchen Sauereien einen core : werfen, und tschuess. Das ist genau das, was als "undefined behavior" gefuerchtet ist, da man praktisch kaum nach einem "segmentation fault" oder einer "protection violation" wieder aufsetzen kann. Ausserdem ist ein 'core' einfach zu spaet! Der Fehler ist (eigentlich) ein Syntaxfehler, da der Compiler "weiss", dass String-Literal eigentlich 'const' sind und nur aus historischen Gruenden als 'non-const' angesehen werden. Der Compiler kann bereits beim Uebersetzen sehen, dass da was im argen ist. Das wird aber, de facto, vom Standard unterdrueckt. Der Compiler koennte eine Warnung ausspucken, aber z.B. gcc-2.7.2 tut das selbst bei -Wall nicht (dafuer gibt es die spezielle Option -Wwrite-strings, die leider nicht in -Wall enthalten ist...). -- dietmar.kuehl@uni-konstanz.de http://www.informatik.uni-konstanz.de/~kuehl I am a realistic optimist - that's why I appear to be slightly pessimistic
Re: Argghh! String-Literals nicht const! (War:Vergleich 'strcmp()' ...)
Author: Ullrich von Bassewitz
Date: Tue, 05 Mar 1996 21:06
Date: Tue, 05 Mar 1996 21:06
39 lines
1935 bytes
1935 bytes
Dietmar Kuehl (kuehl@uzwil.informatik.uni-konstanz.de) wrote:
> Der Fehler ist (eigentlich) ein Syntaxfehler, da der Compiler
> "weiss", dass String-Literal eigentlich 'const' sind und nur aus
> historischen Gruenden als 'non-const' angesehen werden. Der Compiler
> kann bereits beim Uebersetzen sehen, dass da was im argen ist.
Wie soll er das machen? Beispiel:
void Clear (char* S)
{
*S = '\0';
}
int main ()
{
Clear ("Lalle");
return 0;
}
Da der Standard sagt, "Lalle" ist nicht const, ist der Aufruf von Clear
voellig legal. Dass innerhalb der Funktion dann auf den String geschrieben
wird ist auch legal, schliesslich ist der Parameter ein char*.
Wenn die Funktion dann noch in einem anderen Modul steht gibt es keine
Chance fuer den Compiler eine Warnung auszugeben.
Das Problem ist also nicht, dass es ein Syntaxfehler ist, sondern es ist
wirklich ein Problem der Definition von String-Literalen als non-const.
Solange das nicht geaendert wird gibt es fuer den Compiler keine
Moeglichkeit etwas zu tun (zumindest in den meisten Faellen nicht).
Gruss
Uz
--
Ullrich von Bassewitz uz@ibb.schwaben.com
Re: Argghh! String-Literals nicht const! (War:Vergleich 'strcmp()' ...)
Author: Dietmar Kuehl
Date: Wed, 06 Mar 1996 19:53
Date: Wed, 06 Mar 1996 19:53
80 lines
4557 bytes
4557 bytes
Hi,
Ullrich von Bassewitz (uz@wuschel.ibb.schwaben.com) wrote:
: Dietmar Kuehl (kuehl@uzwil.informatik.uni-konstanz.de) wrote:
: > Der Fehler ist (eigentlich) ein Syntaxfehler, da der Compiler
: > "weiss", dass String-Literal eigentlich 'const' sind und nur aus
: > historischen Gruenden als 'non-const' angesehen werden. Der Compiler
: > kann bereits beim Uebersetzen sehen, dass da was im argen ist.
: Wie soll er das machen? Beispiel:
: void Clear (char* S)
: {
: *S = '\0';
: }
: int main ()
: {
: Clear ("Lalle");
Nichts hindert den Compiler daran, DIESEN Aufruf als kritisch anzusehen
und eine Warnung auszuspucken! ... der Compiler WEISS, dass DIESER
Aufruf Gefahren in sich birgt. Sicher, wenn 'Clear()' den String nicht
aendert, wird eine Warnung zuviel ausgegeben. Der beste Weg, diese
Warnung zu verhindern ist allerdings 'Clear()' zu aendern. In Deinem
Beispiel kann man die Deklaration von 'Clear()' nicht aendern und man
sieht also direkt, dass da was faul ist ("undefined behavior" lauert in
diesem Fall in der Funktion 'Clear()').
Nun koennte man behaupten, "Ich kann die Deklaration von 'Clear()' aber
nicht aendern (weil sie aus einer Bibliothek von sonstwo kommt)". Das
ist aber falsch! Wenn 'Clear()' tatsaechlich den String nicht aendert
(und das sollte man tunlichst ueberpruefen, bevor man das macht, was
ich gleich vorschlage!) und es also tatsaechlich sinnvoll ist, ein
String-Literal zu uebergeben, dann kann man die Funktion ueberladen,
z.B. mit dieser:
void Clear(char const *str)
{
Clear(const_cast<char*>(str));
// falls 'const_cast' noch nicht unterstuetzt wird, tut es
// folgendes ganz genauso:
// Clear((char*)str);
// Allerdings ist 'const_cast' unbedingt vorzuziehen (siehe
// "More Effective C++" Item 2).
}
Das ist alles wunderschoen und portable, solang die Funktion wirklich
nicht den String aendert.
: return 0;
: }
: Das Problem ist also nicht, dass es ein Syntaxfehler ist, sondern es ist
: wirklich ein Problem der Definition von String-Literalen als non-const.
: Solange das nicht geaendert wird gibt es fuer den Compiler keine
: Moeglichkeit etwas zu tun (zumindest in den meisten Faellen nicht).
Das sehe ich anders... (siehe oben). Man kann den Compiler einfach
vorsichtiger als noetig sein lassen und ein paar Warnungen zuviel geben
lassen. Da man die zuviel Warnung wieder umgehen kann (siehe oben) ist
das genau das, was man will. Der gcc unterstuetzt das sogar (mit der
Option '-Wwrite-strings', die, wie ich schon sagte, leider nicht in
'-Wall' oder der Default-Setzung enthalten ist). Man muss ich uebrigens
klar machen, dass der Code in Deinem Beispiel "undefined behavior"
produziert, also z.B. das Programm mit einen Segmentation-Fault
abbricht ("abstruerzt"). Das ist schlichtweg katastrophal! Also MUSS
man was dagegen tun, dass sowas passiert. Es ist um so schlimmer, dass
es Compiler gibt, die dafuer Code generieren, bei dem das Programm
NICHT abstuerzt: Wenn man mit einem solchen Compiler entwickelt und es
aber mit einem anderen Compiler irgendwo installiert, treten ggf.
Fehler auf, die beim Testing nicht auftreten konnten! Gruselig. Man
stelle sich vor, der Code wird im Autopilot eines Flugzeugs verwendet!
Da will ich nicht einsteigen: Programmabsturz koennte u.U. mit
Flugzeugabsturz einhergehen... (OK, die werden vermutlich den Code, der
im Flugzeug laeuft mit dem selben Compiler uebersetzen, mit dem sie
testen. Aber man kann ja nie wissen....).
--
dietmar.kuehl@uni-konstanz.de
http://www.informatik.uni-konstanz.de/~kuehl
I am a realistic optimist - that's why I appear to be slightly pessimistic
Re: Argghh! String-Literals nicht const! (War:Vergleich 'strcmp()' ...)
Author: Ullrich von Bassewitz
Date: Sun, 10 Mar 1996 11:43
Date: Sun, 10 Mar 1996 11:43
105 lines
6704 bytes
6704 bytes
Dietmar Kuehl (kuehl@uzwil.informatik.uni-konstanz.de) wrote:
> Nichts hindert den Compiler daran, DIESEN Aufruf als kritisch anzusehen
> und eine Warnung auszuspucken! ... der Compiler WEISS, dass DIESER
> Aufruf Gefahren in sich birgt. Sicher, wenn 'Clear()' den String nicht
> aendert, wird eine Warnung zuviel ausgegeben. Der beste Weg, diese
> Warnung zu verhindern ist allerdings 'Clear()' zu aendern. In Deinem
> Beispiel kann man die Deklaration von 'Clear()' nicht aendern und man
> sieht also direkt, dass da was faul ist ("undefined behavior" lauert in
> diesem Fall in der Funktion 'Clear()').
Ok, wenn Du das so siehst: Natuerlich hindert den Compiler nichts daran.
Genausogut koennte er bei "if (A = B) {" warnen, das ist letzten Endes eine
Philosophiefrage. Aber: Hast Du mal alte Projekte gewartet, die aus Zeiten
stammen, als die Programmierer nichts von const wussten/wissen wollten?
Das was Du sagst kann man schon so durchgehen lassen - vorausgesetzt ich
schreibe neue Programme und/oder habe einen Arbeitgeber, der beide Augen zu-
drueckt, wenn er meine Stundenabrechnungen unterschreibt. Und der hinter mir
steht, wenn ich meine Deadlines nicht einhalte, weil ich um jeden Pointer
eine Klasse und um jede Funktion, die einen "char*" anstelle eines "const
char*" nimmt eine Wrapper Funktion schreibe. Ich kann mir meine Arbeit
natuerlich beliebig kompliziert machen, nur blaeht das meinen Code auf und
bringt in vielen Faellen wenig bis ueberhaupt nichts fuer die Codequalitaet.
Da Du immer fuer Wrapper Klassen- und Funktionen argumentierst: Hast Du Dir
schonmal ueberlegt, wieviel zusaetzlicher Code in realen Projekten dabei
entsteht? Ist Dir klar, dass jede weitere Zeile Code eine zusaetzliche
Fehlerquelle darstellt? Was glaubst Du, wieviele Programme ich schon gesehen
habe, die Fehler im Code fuer die Fehlerbehandlug enthielten? Witzigerweise
ist dieser Code wesentlich anfaelliger fuer Fehler,
* weil er weniger getestet wird,
* weil innerhalb dieses Codes unter Umstaenden bestimmte Mechanismen
nicht mehr funktionieren, die der Programmierer aus Gewohnheit annimmt
(Beispiel von vor wenigen Tagen: Der Programmierer prueft, ob der Zeiger
auf den Kontrollblock gueltig ist. Ist er das nicht, springt er in den
Fehlerbehandlungszweig und versucht eine Meldung zu loggen. Dummerweise
vergisst er aber dabei, dass die Routine zum Loggen des Fehlers genau
diesen Kontrollblock benoetigt und deshalb crasht).
* weil nicht voraussagbar ist, welche Fehler tatsaechlich auftreten, in
welcher Reihenfolge und Kombination. Fuer diesen Effekt sind vor allem
zwei Dinge verantwortlich:
- Fehler in einer Routine koennen aus fehlerhaftem Code an anderer Stelle
entstehen. Und Programmierer sind bekanntermassen erfinderisch :-)
- Reale Programme interagieren mit der Umwelt. Sei es, dass vor dem
Bildschirm ein Benutzer sitzt, der sich nicht immer so verhaelt, wie
der Programmierer es erwartet, oder eine Maschine, die auch nicht
immer das tut, was man erwarten sollte.
> produziert, also z.B. das Programm mit einen Segmentation-Fault
> abbricht ("abstruerzt"). Das ist schlichtweg katastrophal! Also MUSS
Auch hier bin ich mal wieder nicht Deiner Meinung :-) Ein Segmentation Fault
mit folgendem Code Dump ist in vielen Faellen eine recht vernuenftige Sache,
zumindest in "realen" Programmen, warum steht teilweise schon weiter oben.
Es mag ja sein, dass ich nicht ueber den letzten Schrei in der C++
Entwicklung informiert bin (ich bin der erste, der das zugibt). Aber ich
mache jetzt schon eine geraume Zeit Software und verdiene mein Geld damit.
Und deshalb habe ich auch so meine Erfahrungen. Dazu gehoert:
* Die Qualitaet der Software haengt nicht von der verwendeten Programmier-
sprache (wenn man Assembler mal aussen vor laesst). Das heisst gleich-
zeitig, dass die Qualitaet von Software auch nicht von irgendwelchen
Sprachkonstrukten abhaengt, die die eine Sprache hat und die andere nicht.
* Die Qualitaet von Software haengt nicht oder sehr wenig von Regeln zur
Verwendung/Vermeidung von Sprachkonstrukten ab. Zu diesen Regeln gehoeren
Dinge wie "Verwende keine gotos", "Verwende keine Pointer", "Das ?:
Konstrukt ist des Teufels" usw. Die tatsaechlichen Probleme liegen in
voellig anderen Bereichen, die meist mit Organisation und Planung zu
tun haben.
* Komplizierte Sprachfeatures/Bibliotheken werden von den meisten
Programmierern gemieden. Ein nettes Beispiel aus der letzten Zeit war
eine Library-Funktion in einer Bibliothek, zu der der Programmierer
einen Kommentar dazugeschrieben hatte, es gaebe zwar in einem anderen
Modul jede Menge Funktionen, die sich mit derselben Problemstellung
herumschlagen wuerden, nur waeren diese so kompliziert, dass er sich
nicht sicher gewesen sei, dass sie auch das tun, was er wolle, und
deshalb haette er hier nochmal eine einfach und uebersichtliche Funktion
hinzugefuegt.
Wenn es Regeln gibt, solche Features/Bibliotheken trotzdem zu verwenden,
dann fuehrt das zu qualitativ schlechterem Code. Insofern stehe ich C++
(und vor allem dem neuen Standard) skeptisch gegenueber. Wenn Du selber
sagst, man braucht jahrelange Erfahrung um C++ richtig zu benutzen, wie
finanziere ich dann die Einarbeitung meiner neuen Mitarbeiter? Und
welche Fehler machen diese, wenn ich sie (gezwungenermassen) in
Projekten einsetze, wenn sie diese Erfahrung noch nicht haben? Und
warum soll ich dann ueberhaupt C++ verwenden, wenn die Verwendung
anderer Sprachen auch keine qualitativ schlechtere Software ergibt?
Fragen ueber Fragen :-)
Gruss
Uz
P.S.: Knapp ueber 100 - ich hoffe das geht noch :-)
--
Ullrich von Bassewitz uz@ibb.schwaben.com
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads