🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

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)
#1708
Author: Dietmar Kuehl
Date: Wed, 28 Feb 1996 23:46
93 lines
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)
#1710
Author: Ullrich von Bassewitz
Date: Thu, 29 Feb 1996 07:36
43 lines
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)
#1717
Author: Bernd Eggink
Date: Thu, 29 Feb 1996 12:01
47 lines
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)
#1725
Author: Joachim Zobel
Date: Sun, 03 Mar 1996 00:36
41 lines
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)
#1726
Author: Joachim Zobel
Date: Sun, 03 Mar 1996 00:41
41 lines
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)
#1731
Author: Dietmar Kuehl
Date: Sun, 03 Mar 1996 20:40
70 lines
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)
#1740
Author: Bernd Eggink
Date: Mon, 04 Mar 1996 10:47
25 lines
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()' ...)
#1746
Author: Joachim Zobel
Date: Mon, 04 Mar 1996 12:52
33 lines
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()' ...)
#1752
Author: Frank Thilo
Date: Mon, 04 Mar 1996 21:43
35 lines
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()' ...)
#1753
Author: Dietmar Kuehl
Date: Mon, 04 Mar 1996 22:52
40 lines
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()' ...)
#1755
Author: Oliver Rebach
Date: Tue, 05 Mar 1996 07:39
28 lines
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)
#1760
Author: Nico Josuttis
Date: Tue, 05 Mar 1996 15:57
36 lines
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()' ...)
#1762
Author: Dietmar Kuehl
Date: Tue, 05 Mar 1996 16:44
21 lines
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()' ...)
#1769
Author: Ullrich von Bassewitz
Date: Tue, 05 Mar 1996 21:06
39 lines
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()' ...)
#1773
Author: Dietmar Kuehl
Date: Wed, 06 Mar 1996 19:53
80 lines
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()' ...)
#1799
Author: Ullrich von Bassewitz
Date: Sun, 10 Mar 1996 11:43
105 lines
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