baz = foo->bar(3);
und dann zu zeigen, was es alles für mögliche Kontexte gibt, die man
beachten muß, um sich sicher zu sein, daß man versteht, was dieses Zeile
da eigentlich genau tut.
Ich will hauptsächlich darauf abheben, daß einem jemand ein an
kompilierendes und linkendes Codestück gibt, aber man exorbitant Kontext
braucht, um a) das parsen und b) erklären zu können, was dieser Code
tut.
Daher appelliere ich hiermit an die ganzen kranken Gestalten hier. Holt
mal aus euren Giftschränken die Details raus und postet sie.
Wer was substanzielles beisteuert (und das möchte) wird
selbstverständlich dankend erwähnt.
Stichwörter bisher:
- Namespaces, using-Deklarationen irgendwo ganz anders im Code.
- Templates, partielle Spezialisierung
- Namensauflösung bei Mehrfachvererbung (auch virtueller)
- Überladen, auch von Operatoren
- Bei Vererbung Überschriebene virtuelle Funktionen
- Implizite Typkonvertierung
- Temp-Variablen und Copy-Konstruktoren
Auf den Präprozessor wollte ich nicht einhauen, weil es um C++ geht,
nicht um den von C geerbten Teil.
Ich wollte auch auf vtable-Bloat eingehen, und mich über endlose
Glue-Wrapper aufregen, aber das ist eher Randprogramm. In der
Hauptsache soll es darum gehen, daß es fast unmöglich ist, ein kleines
Stück C++-Code außerhalb der gesamten Kompilationseinheit zu betrachten.
Zuschriften gerne auch per Mail, aber ich vermute mal, die ganze Rotte
hier würde sich über eine schöne C++-Schlammschlacht freuen.
Felix
--
I don't deserve this award, but I have arthritis and I don't
deserve that either.
--Jack Benny
> Für einen demnächst zu haltenden Vortrag suche ich noch schlagkräftige
> Argumente, wieso C++ Scheiße ist.
Man kann in jeder Sprache... *sigh* lassen wir das. Geh draussen
spielen.
hth,
Christoph
Also mit z.B. Brainfuck http://de.wikipedia.org/wiki/Brainfuck kann man
eigentlich nicht viel Schaden anrichten. *g*
Andreas
--
Wer mir per Mail antworten möchte sollte 'erdbeere' im Betreff erwähnen,
sonst wird die Mail zusammen mit SPAM und Würmern ungelesen gelöscht.
> Für einen demnächst zu haltenden Vortrag suche ich noch schlagkräftige
> Argumente, wieso C++ Scheiße ist. Die konkrete Vortragsidee war, ein
Ganz einfach. Auf dem Weg von der unbenutzbaren Zukunftssprache zur
unbenutzbaren Legacy-Lösung veraltet, und zwar genau in dem Moment, wo
es eigentlich ganz gut zu gebrauchen gewesen wäre...
Also so wie fast alle anderen Sprachen auch. ;)
Jochen
--
No smilies were harmed in the making of this message ;)
Na das ist doch klar: Weil $CURRENT_HYPE_LANGUAGE viel besser ist. ;-)
ciao, Joseph
Wer hat denn dieses Kleinkind hier reingelassen, ohne ihm Respekt vor
in Würde ergrauten Regulars zu vermitteln? Sheesh, immer muß _ich_ hier
aufräumen.
*türhinterihmschließ*
Felix von Leitner <usenet-...@fefe.de> writes:
> Wer hat denn dieses Kleinkind hier reingelassen, ohne ihm Respekt vor
> in Würde ergrauten Regulars zu vermitteln?
^^^^^^^^^^^^^^^^^^^^^^^^^^^
also für manchen Kommentar möchtest du da drüber nochmal nachdenken. Vor
allem in diesem Thread.
Bis dann
Markus
--
> schön für Sie ist, dass Sie die blauen Bildschirme von Microsoft
> deuten können(scheint ja so) ...
Das ist ja wohl nicht so schwierig. Meine Deutung seinerzeit war:
"Wirf Windows weg!" Und so tat ich es. - Dines und Lasse Klieman in dscf
Zum Aufwärmen:
(foo)+a*b
Das braucht selbst in C schon Kontext, nämlich ob es "cast(a) mal b"
oder "foo plus (a mal b)" ist. Und in Java und C# selbstverständlich auch.
C++-spezifisch ist sowas wie
typ(foo[riesen_ausdruck])
Geht die Zeile z.B. mit '+3' weiter, wird da 'foo[riesen_ausdruck]' nach
'typ' gecastet und 3 addiert. Geht die Zeile mit ';' weiter, wird eine
neue Arrayvariable eingeführt.
> - Namespaces, using-Deklarationen irgendwo ganz anders im Code.
Ist ja nun nicht wirklich saugstark, zumal die bösen Sachen eh
Mehrdeutigkeitsfehler bringen.
> - Templates, partielle Spezialisierung
template<int i> struct X { };
template<> struct X<4> { static void z(bool); };
int test() {
X<sizeof(long)>::z("foo"); // gültig auf x86, nicht auf Alpha
}
Ähnliches geht aber in C auch ('int x[sizeof(long)-4]').
> - Namensauflösung bei Mehrfachvererbung (auch virtueller)
Vor Urzeiten hatte ich mal den hier:
struct a{typedef int foo;};struct a1:a{};struct a2:a{};
#define X(b,a) struct a##1:b##1,b##2{};struct a##2:b##1,b##2{};
X(a,b)X(b,c)X(c,d)X(d,e)X(e,f)X(f,g)X(g,h)X(h,i)X(i,j)X(j,k)X(k,l)
X(l,m)X(m,n) n1::foo main(){}
an dem ein gcc 3.x eine halbe Stunde compiliert. Das baut eine hübsch
verschachtelte Klassenhierarchie auf, und der Compiler muss alle Pfade
prüfen, um 'n1::foo' aufzulösen. gcc verwendet einen O(4^n)-Algorithmus,
es ist aber auch wesentlich schneller zu schaffen.
> - Überladen, auch von Operatoren
Bitteschön:
template<typename T>
struct Loop {
Loop<T*> operator->();
};
Loop<int> i, j = i->foo;
Über die Verkettung von "->" ist es letztenendes möglich, den Compiler
beliebige Rekursionen rechnen zu lassen, nur um festzustellen, ob ein
C++-Programm gültig ist. Bei obigem rechnet er ewig, was das laut Norm
geforderte Verhalten für dieses Programm ist.
> Ich wollte auch auf vtable-Bloat eingehen, und mich über endlose
> Glue-Wrapper aufregen, aber das ist eher Randprogramm.
In des tumben Toren Hand, ist das beste Werkzeug Tand. Wenn ich virtuel-
len Dispatch brauche, schreibe ich natürlich eine Klasse mit virtuellen
Methoden hin, und dann ist das in C++ nicht mehr (Maschinen-)Code als in
C. Wenn ich keinen virtuellen Dispatch brauche, schreib ich auch keinen hin.
> In der Hauptsache soll es darum gehen, daß es fast unmöglich ist, ein
kleines
> Stück C++-Code außerhalb der gesamten Kompilationseinheit zu betrachten.
Ist es aber, siehe oben, in C auch :-)
> Zuschriften gerne auch per Mail, aber ich vermute mal, die ganze Rotte
> hier würde sich über eine schöne C++-Schlammschlacht freuen.
Letztenendes halte ich C++ immer noch für die am wenigsten stinkende
halbwegs portable ernsthafte Programmiersprache. Alles andere ist nur in
der Theorie portabel und/oder verfügbar.
Stefan
ACK.
> C++-spezifisch ist sowas wie
> typ(foo[riesen_ausdruck])
> Geht die Zeile z.B. mit '+3' weiter, wird da 'foo[riesen_ausdruck]' nach
> 'typ' gecastet und 3 addiert. Geht die Zeile mit ';' weiter, wird eine
> neue Arrayvariable eingeführt.
Das ist zwar widerlich, aber das kann man sich angewöhnen, und dann
sieht man das mit einem Blick. Ich meine so Sachen wie eine Codezeile,
die völlig harmlos aussieht, aber bei näherer Betrachtung siehst du
dann, daß du diese komplette Datei und fünfzehn andere Dateien komplett
gelesen haben mußt, um diese eine Zeile verstehen zu können.
Ich habe da auch eine Entwicklung durchgemacht, und fand am Anfang z.B.
Referenzen eine großartige Sache.
Dann habe ich mich mal beim Code Lesen beobachtet. Durch C Code kann
ich in nicht-pathologischen Fällen durchscrollen, dabei den Sinn
mitnehmen, und gefährliche Stellen fallen mir auf. Das liegt u.a.
daran, daß man bei
d=foo(a,&b,c);
erkennt, daß d und b geschrieben werden. Gut, man braucht immer noch
Kontext, ob a und b Zeiger auf irgendwas sind. Aber bei C++ können
plötzlich auch Skalare ohne & übergeben werden und dabei geschrieben
werden. Das ist ein echter Nachteil.
Meine zentrale Kritik an C++ ist, daß da das Programmieren optimiert
wird, nicht das Lesen und Warten des Codes. Dabei macht es nur 10-20%
aus.
> > - Namespaces, using-Deklarationen irgendwo ganz anders im Code.
> Ist ja nun nicht wirklich saugstark, zumal die bösen Sachen eh
> Mehrdeutigkeitsfehler bringen.
Ich schau mal, ob ich einen schönen expressiven Fall konstruiert kriege.
> > - Templates, partielle Spezialisierung
> template<int i> struct X { };
> template<> struct X<4> { static void z(bool); };
> int test() {
> X<sizeof(long)>::z("foo"); // gültig auf x86, nicht auf Alpha
> }
Ich dachte eher an sowas wie daß jemand eine vorgeblich harmlose und
bekannte STL-Funktion aufruft, aber deren Sinn durch eine fiese
Spezialisierung anderswo komplett entstellt wird.
Das wird zwar in normalem Code nicht passieren, aber als Code Auditor
soll man ja gerade die ungewöhnlichen Fälle finden und kann daher nicht
davon ausgehen, daß sie nicht vorkommen.
Ich suche noch ein Beispiel für eine besonders perverse Fehlermeldung.
Ich erinnere mich da an ganz furchtbare STL-Meldungen, aber gcc hat das
ein bißchen umgestellt. Heute kriegt man statt einer Zeile der Länge
500 dann lieber 7 Zeilen mit jeweils 80 Zeichen. Ich guck mal, ob ich
da nicht doch noch was konstruiert kriege. Ne Map von Strings und da
irgendnen falschen Iterator übergeben oder so. Ich finde schon was
schönes.
> Ähnliches geht aber in C auch ('int x[sizeof(long)-4]').
ACK, benutzt autoconf vorbildlich für cross-compiler-fähige
sizeof-Tests.
> > - Namensauflösung bei Mehrfachvererbung (auch virtueller)
> Vor Urzeiten hatte ich mal den hier:
> struct a{typedef int foo;};struct a1:a{};struct a2:a{};
> #define X(b,a) struct a##1:b##1,b##2{};struct a##2:b##1,b##2{};
> X(a,b)X(b,c)X(c,d)X(d,e)X(e,f)X(f,g)X(g,h)X(h,i)X(i,j)X(j,k)X(k,l)
> X(l,m)X(m,n) n1::foo main(){}
> an dem ein gcc 3.x eine halbe Stunde compiliert. Das baut eine hübsch
> verschachtelte Klassenhierarchie auf, und der Compiler muss alle Pfade
> prüfen, um 'n1::foo' aufzulösen. gcc verwendet einen O(4^n)-Algorithmus,
> es ist aber auch wesentlich schneller zu schaffen.
gcc braucht inzwischen ~ 90 Sekunden dafür.
icc 10 habe ich auf der selben Hardware nach 90 Minuten (!) abgebrochen.
> > - Überladen, auch von Operatoren
> Bitteschön:
> template<typename T>
> struct Loop {
> Loop<T*> operator->();
> };
> Loop<int> i, j = i->foo;
> Über die Verkettung von "->" ist es letztenendes möglich, den Compiler
> beliebige Rekursionen rechnen zu lassen, nur um festzustellen, ob ein
> C++-Programm gültig ist. Bei obigem rechnet er ewig, was das laut Norm
> geforderte Verhalten für dieses Programm ist.
Habe ich schon voll Freude im Archiv gefunden und mich darüber amüsiert.
> > Ich wollte auch auf vtable-Bloat eingehen, und mich über endlose
> > Glue-Wrapper aufregen, aber das ist eher Randprogramm.
> In des tumben Toren Hand, ist das beste Werkzeug Tand. Wenn ich virtuel-
> len Dispatch brauche, schreibe ich natürlich eine Klasse mit virtuellen
> Methoden hin, und dann ist das in C++ nicht mehr (Maschinen-)Code als in
> C. Wenn ich keinen virtuellen Dispatch brauche, schreib ich auch keinen hin.
Na die meisten Klassenbibliotheken haben virtuelle Funktionen. Und der
Compiler muß dann eben Funktionen reinlinken, die nie aufgerufen werden,
weil ein Zeiger in einer vtable auf sie verweist. So gerne wie die
Leute da draußen Vererbung und virtuelle Funktionen verwenden, läßt sich
das gar nicht verhindern in Programmen in der Praxis.
Ich muß mal gucken, ob ich da ein besonders brutales Beispiel finde.
Qt oder MFC oder sowas. Ich weiß nicht, wer da besonders schlecht drauf
ist, aber wir sind uns ja wohl einig, daß das ein Problem ist in der
Praxis, also wird es da auch schöne Beispiele geben.
> > In der Hauptsache soll es darum gehen, daß es fast unmöglich ist, ein
> > kleines Stück C++-Code außerhalb der gesamten Kompilationseinheit zu
> > betrachten.
> Ist es aber, siehe oben, in C auch :-)
Ich bestreite ja gar nicht, daß die anderen Sprachen auch alle Scheiße
sind. :-)
> > Zuschriften gerne auch per Mail, aber ich vermute mal, die ganze Rotte
> > hier würde sich über eine schöne C++-Schlammschlacht freuen.
> Letztenendes halte ich C++ immer noch für die am wenigsten stinkende
> halbwegs portable ernsthafte Programmiersprache. Alles andere ist nur in
> der Theorie portabel und/oder verfügbar.
A...aber C#!1!! :-)
Felix
PS: Das lief so. Ich habe zum CCC Camp drei Vorträge eingereicht.
Einen wichtigen, coolen, über Integer Overflows, von dem ich mir sicher
war, daß der genommen wird. Und zwei andere, die auch interessant sind,
aber halt nicht so wichtig. Ich sagte ihnen, sie sollen einen
auswählen, in der festen Annahme, daß es der Int Overflow Vortrag würde.
Sie haben stattdessen die beiden anderen gewählt. Seufz.
Im Dritten geht es darum, welche Optimierungen man nicht im Quellcode
durchführen soll, weil sie eh schon der Compiler für einen macht, und
man die Sourcen nur weniger gut lesbar macht. Ist vielleicht auch für
den einen oder anderen interessant, falls da jemand Ideen beisteuern
will oder was zu zu sagen hat.
und die nächste CPU-Generation das eh wieder völlig anders haben will,
> und man die Sourcen nur weniger gut lesbar macht.
-funroll-all-loops?
> Ich suche noch ein Beispiel für eine besonders perverse Fehlermeldung.
Reicht es nicht, daß C nach "Datei nicht gefunden" oder "Syntaxfehler"
weitercompiliert, um den Bildschirm sinnloserweise mit Folgefehlern
zuzumüllen? Oder "Syntax error before ','", wenn man genug ',' hat?
>> > Ich wollte auch auf vtable-Bloat eingehen, und mich über endlose
>> > Glue-Wrapper aufregen, aber das ist eher Randprogramm.
>> In des tumben Toren Hand, ist das beste Werkzeug Tand. Wenn ich virtuel-
>> len Dispatch brauche, schreibe ich natürlich eine Klasse mit virtuellen
>> Methoden hin, und dann ist das in C++ nicht mehr (Maschinen-)Code als in
>> C. Wenn ich keinen virtuellen Dispatch brauche, schreib ich auch keinen hin.
>
> Na die meisten Klassenbibliotheken haben virtuelle Funktionen. Und der
> Compiler muß dann eben Funktionen reinlinken, die nie aufgerufen werden,
> weil ein Zeiger in einer vtable auf sie verweist. So gerne wie die
> Leute da draußen Vererbung und virtuelle Funktionen verwenden, läßt sich
> das gar nicht verhindern in Programmen in der Praxis.
Solange die Funktionen in einer Shared Library vergammeln, stört das nur
wenig.
> Im Dritten geht es darum, welche Optimierungen man nicht im Quellcode
> durchführen soll, weil sie eh schon der Compiler für einen macht, und
> man die Sourcen nur weniger gut lesbar macht. Ist vielleicht auch für
> den einen oder anderen interessant, falls da jemand Ideen beisteuern
> will oder was zu zu sagen hat.
Interessant könnte dort sein, daß man teilweise mit der Nutzung eines int
als Zwischenspeicher für *char_ptr den Code beschleunigen kann.
--
S.U.Z.U.K.I.: Synthetic Unit Zoned for Ultimate Killing and Infiltration
-- http://www.brunching.com/toys/toy-cyborger.html (down)
Friß, Spammer: lgcs...@9aDgMgiZ.7eggert.dyndns.org
Felix von Leitner <usenet-...@fefe.de> writes:
> Ich habe da auch eine Entwicklung durchgemacht, und fand am Anfang z.B.
> Referenzen eine großartige Sache.
>
> Dann habe ich mich mal beim Code Lesen beobachtet. Durch C Code kann
> ich in nicht-pathologischen Fällen durchscrollen, dabei den Sinn
> mitnehmen, und gefährliche Stellen fallen mir auf. Das liegt u.a.
> daran, daß man bei
>
> d=foo(a,&b,c);
>
> erkennt, daß d und b geschrieben werden. Gut, man braucht immer noch
> Kontext, ob a und b Zeiger auf irgendwas sind. Aber bei C++ können
> plötzlich auch Skalare ohne & übergeben werden und dabei geschrieben
> werden. Das ist ein echter Nachteil.
Zugegebenermaßen mag das sogar ein Nachteil sein, daß man da mehr gucken
muss. Andererseits sind Referenzen halt "billig" wie Zeiger, man kann
sie aber nicht verkacken, indem man sie mit ungültigen Werten
befüllt. Wenn man sich da an sinnvolle Konventionen hält (alles
standardmäßig als const &, schreibbare Parameter ohne const), dann
genügt ein kurzer Blick in die Schnittstelle und man weiß
bescheid. Damit ist das, was man lesen muss, zwar umfangreicher, aber
immernoch stark lokal (es beschränkt sich auf die Deklaration der
Funktion, die man aufruft. Was weiter unten passiert kann einem Hupe
sein.)
> Meine zentrale Kritik an C++ ist, daß da das Programmieren optimiert
> wird, nicht das Lesen und Warten des Codes. Dabei macht es nur 10-20%
> aus.
Sehe ich anders. Dank der Möglichkeiten der Sprache _kann_ ich in C++
Sachen schreiben wie:
Matrix a, b, c;
...
c = a + b;
und die bedeuten dann das, was man intuitiv vermutet. Zugegebenermaßen:
sie können auch etwas komplett anderes bedeuten, wenn der Entwickler von
Matrix Mist gebaut hat. Womit wir wieder bei dem Problem des Werkzeugs
in der Hand von Unfähigen wären...
> Ich dachte eher an sowas wie daß jemand eine vorgeblich harmlose und
> bekannte STL-Funktion aufruft, aber deren Sinn durch eine fiese
> Spezialisierung anderswo komplett entstellt wird.
Oh, mein Lieblingsfehler:
class Str
{
char *field;
public:
A()
{
field = new char[100];
}
A &operator=(A const &src)
{
delete[] field;
field = new char[strlen(src.field)];
strcpy(src.field, field);
return *this;
}
};
Finde den Fehler! (Hint: int main() { A a; a=a; })
> Na die meisten Klassenbibliotheken haben virtuelle Funktionen. Und der
> Compiler muß dann eben Funktionen reinlinken, die nie aufgerufen werden,
> weil ein Zeiger in einer vtable auf sie verweist. So gerne wie die
> Leute da draußen Vererbung und virtuelle Funktionen verwenden, läßt sich
> das gar nicht verhindern in Programmen in der Praxis.
Die meisten Klassenbibliotheken sind in shared objects versteckt, so daß
die Funktionen letztlich einmal vorliegen. Da überwiegt dann doch der
Vorteil der einfachen Erweiterbarkeit durch Ableitung. Ok, wenn man
natürlich die Java-Variante wählt und erstmal eine Klasse
class Object
{
public:
virtual ~Object() {}
};
definiert, dann muss man sich über Bloat nicht wundern.
> Ich muß mal gucken, ob ich da ein besonders brutales Beispiel finde.
> Qt oder MFC oder sowas. Ich weiß nicht, wer da besonders schlecht drauf
> ist, aber wir sind uns ja wohl einig, daß das ein Problem ist in der
> Praxis, also wird es da auch schöne Beispiele geben.
Grade bei Widget-Libs ist die Ableitungssache nunmal sehr praktisch für
die Integration eigener Widgets.
>> Letztenendes halte ich C++ immer noch für die am wenigsten stinkende
>> halbwegs portable ernsthafte Programmiersprache. Alles andere ist nur in
>> der Theorie portabel und/oder verfügbar.
>
> A...aber C#!1!! :-)
Ist portabel auf embedded systems? (Und wehe jetzt kommt mir einer mit
dem komischen .NET Compact oder wie das heißt!)
> Im Dritten geht es darum, welche Optimierungen man nicht im Quellcode
> durchführen soll, weil sie eh schon der Compiler für einen macht, und
> man die Sourcen nur weniger gut lesbar macht. Ist vielleicht auch für
> den einen oder anderen interessant, falls da jemand Ideen beisteuern
> will oder was zu zu sagen hat.
Duff's Device
Oder, mein persönlicher Liebling (vor einiger Zeit sinngemäß gesehen):
#define RDTSC "Bytecode für rdtsc"
...
long getTime()
{
asm
{
RDTSC
}
}
Wie gesagt: sinngemäß, die genaue Syntax war anders. Funktionierte
wunderbar, gab genaue Zeitmessungen. Nur die Mac-Portierung wollte von
Zeit zu Zeit mit "illegal opcode" irgendwie nicht mehr...
Bis dann
Markus
--
datensicherung...datensicherung...
da hab' ich mal was von gehört...mal sehen, ob sich das durchsetzt
- BlueBear auf heise.de
Es ist leider nicht so einfach, den Dispatch zu verbieten. Das ist
insbesondere für die Funktionen übel, die glauben, es gäbe hier keinen
Dispatch, weil sie aus Zeiten vor der Erweiterung stammen.
Andere Sprachen erfordern die Angabe des Dispatch explizit (Ada mittels
T'Class Typen).
Um dem im Compilerschritt zu finden, brauchst Du pur funktionale Sprachen
oder SPARK. Aliasingeffekte sind übel.
Kurzfassung des o.g. Fehlers in der klassischen Form:
inline void inplace_swap(int &a,int &b) {
a ^= b;
b ^= a;
a ^= b;
}
Zu Bloat in Bibliotheken: Ist es bei C++ immer noch üblich, daß die
Standardbibliothek im Sourcecode vorliegt (als gigantische Templatesammlung)
und bei der modulweisen Übersetzung pro compilierter Datei eine Instanz der
Standardbibliotheksfunktionen dazulinkt?
Muß es C++ sein oder reichen auch Objekte aus C-structs? Ich versuche
gerade PETSc (http://www-unix.mcs.anl.gov/petsc) mit intel-C/C++/Fortran
10.0 zu übersetzen und wundere mich, warum das icc-Backend die 4GB RAM
vollaufen läßt bis nichts mehr geht -- mit intel 9.1 hatte doch
schließlich auch alles funktioniert. Also mal schnell in den Code
geschaut, was los ist... Meine Omma hat immer gesagt "Im Krankenhaus
hamse den Erwin aufgeschnitten und gleich wieder zugemacht."
Gruß,
Henry
> Matrix a, b, c;
> ...
> c = a + b;
> und die bedeuten dann das, was man intuitiv vermutet. Zugegebenermaßen:
> sie können auch etwas komplett anderes bedeuten, wenn der Entwickler von
> Matrix Mist gebaut hat. Womit wir wieder bei dem Problem des Werkzeugs
> in der Hand von Unfähigen wären...
Das Problem ist, daß Code Auditing als kommerzielle Dienstleistung (die
ich anbiete) üblicherweise nicht für Code eingekauft wird, der von
perfekten Entwicklern gemacht wurde. Im Gegenteil muß man davon
ausgehen, daß die nicht wußten, was sie da genau taten, und so lange
rumgefummelt haben, bis der Compiler es fraß.
> > Na die meisten Klassenbibliotheken haben virtuelle Funktionen. Und der
> > Compiler muß dann eben Funktionen reinlinken, die nie aufgerufen werden,
> > weil ein Zeiger in einer vtable auf sie verweist. So gerne wie die
> > Leute da draußen Vererbung und virtuelle Funktionen verwenden, läßt sich
> > das gar nicht verhindern in Programmen in der Praxis.
> Die meisten Klassenbibliotheken sind in shared objects versteckt, so daß
> die Funktionen letztlich einmal vorliegen. Da überwiegt dann doch der
> Vorteil der einfachen Erweiterbarkeit durch Ableitung. Ok, wenn man
> natürlich die Java-Variante wählt und erstmal eine Klasse
> class Object
> {
> public:
> virtual ~Object() {}
> };
> definiert, dann muss man sich über Bloat nicht wundern.
Ich habe das Argument gehört (ernsthaft vorgetragen!), daß C++ ALLE
Funktionen virtual machen sollte, weil die verlorene CPU-Zeit billiger
sei als die Zeit der Programmierer für das Nachtragen der vergessenen
virtual Deklarationen.
Felix
> inline void inplace_swap(int &a,int &b) {
> a ^= b;
> b ^= a;
> a ^= b;
> }
Sehr schön :-)
> Zu Bloat in Bibliotheken: Ist es bei C++ immer noch üblich, daß die
> Standardbibliothek im Sourcecode vorliegt (als gigantische Templatesammlung)
> und bei der modulweisen Übersetzung pro compilierter Datei eine Instanz der
> Standardbibliotheksfunktionen dazulinkt?
Ja, aber der GNU Linker kann dann Duplikate der selben
Template-Instanziierung rausfiltern.
Hilft natürlich nicht gegen den Inline-Kram.
Felix
Das ist dann in Java "gefixt" worden.
SCNR,
Bernd
--
"What happens when you read some doc and either it doesn't answer your
question or is demonstrably wrong? In Linux, you say "Linux sucks" and
go read the code. In Windows/Oracle/etc you say "Windows sucks" and
start banging your head against the wall." - Denis Vlasenko on lkml
Tja, das groesste Problem sind die Erbschaften von C und die gesamte
Komplexitaet. Alles in allem ergibt das eine Programmiersprache die nur
wenige Programmierer die sie einsetzen wirklich ausreichend verstehen, was
dann letztendlich zu miesem Code/Design/Performance/Maintainability fuehrt.
Ansonsten ist es eine Sprache in der man durchaus recht produktiv sein
kann.
> Zuschriften gerne auch per Mail, aber ich vermute mal, die ganze Rotte
> hier würde sich über eine schöne C++-Schlammschlacht freuen.
Oh, entschuldige, ich dachte es geht hier um die Wahrheitsfindung.
Uli
Und in AMD-SMP-Systemen gibt's nette Zeitsprünge (gern auch rückwärts),
wenn der Thread mal die CPU wechselt...
ciao, Joseph
Nein. Diverse der Template-Klassen sind auch spezialisiert (IOStreams,
strings) und bieten sich damit an in dynamischen oder statischen Libs
vorkompiliert zu sein.
> und bei der modulweisen Übersetzung pro compilierter Datei eine
> Instanz der Standardbibliotheksfunktionen dazulinkt?
QOI, aber ich kann mir keine ernsthafte Implemetierung vorstellen die nicht
doppelte instanzen spaetestens beim Linken wieder raus wirft.
Uli
> Ich habe das Argument gehört (ernsthaft vorgetragen!), daß C++ ALLE
> Funktionen virtual machen sollte, weil die verlorene CPU-Zeit billiger
> sei als die Zeit der Programmierer für das Nachtragen der vergessenen
> virtual Deklarationen.
Stimmt, die CPU-Zeit zahlt der Kunde.
--
Top 100 things you don't want the sysadmin to say:
61. Yes, I chowned all the files to belong to pvcs. Is that a problem to
you?
Friß, Spammer: 9...@pzcOjifg.7eggert.dyndns.org bqo...@A69.7eggert.dyndns.org
Ich kann zwar kein C++, aber ich glaube, jetzt habe ich's verstanden.
>
> Um dem im Compilerschritt zu finden, brauchst Du pur funktionale Sprachen
> oder SPARK. Aliasingeffekte sind übel.
>
> Kurzfassung des o.g. Fehlers in der klassischen Form:
>
> inline void inplace_swap(int &a,int &b) {
> a ^= b;
> b ^= a;
> a ^= b;
> }
Cool! Quantenstatistische Effekte in einem Programm!
-is
> Muß es C++ sein oder reichen auch Objekte aus C-structs? Ich versuche
> gerade PETSc (http://www-unix.mcs.anl.gov/petsc) mit intel-C/C++/Fortran
> 10.0 zu übersetzen und wundere mich, warum das icc-Backend die 4GB RAM
> vollaufen läßt bis nichts mehr geht -- mit intel 9.1 hatte doch
> schließlich auch alles funktioniert. Also mal schnell in den Code
> geschaut, was los ist... Meine Omma hat immer gesagt "Im Krankenhaus
> hamse den Erwin aufgeschnitten und gleich wieder zugemacht."
Kenn ich nicht - aber das Gefühl kenne ich.
<Higgins>
Vor nicht allzuvielen Jahren hatte ich einen Lieblingsdigitalphotodrucker,
der Upload per ftp anbietet, leider in Auftragsgrundgebühr und Kosten pro
Photo etwas teurer ist als Mitbewerber.
Und es begab sich, dass ein neuer Mitbewerber auftauchte, dessen WWW-
Uploadschirm sich immerhin mit links bedienen ließ.
Ok, dachte ich - ausprobieren. 50 Photos auf der Platte[1] markiert, upload
angeklickt, solang was anderes gemacht.
<Platte>Rödel...</Platte>
Time passes... LEDs am Router blinken.
<Platte>Rödel...</Platte>
Time passes... LEDs am Router blinken.
Time passes... LEDs am Router blinken.
<Platte>RödelRödelRödelRödelRödel...</Platte>
<Platte>RödelRödelRödelRödelRödel...</Platte>
Segmentation Violation. Core dumped.\nmarie 666%
Huch? Zu viele Dateien auf einmal?
Ok, zip-Archive sind auch erlaubt. 7 Zip-Archive zu je 7 Photos erstellt,
angeklickt, nochmal.
<Platte>Rödel...</Platte>
Time passes... LEDs am Router blinken.
<Platte>Rödel...</Platte>
Time passes... LEDs am Router blinken.
Time passes... LEDs am Router blinken.
<Platte>RödelRödelRödelRödelRödel...</Platte>
<Platte>RödelRödelRödelRödelRödel...</Platte>
Segmentation Violation. Core dumped.\nmarie 666%
)!&@!@ Links. Wo sind die sourcen?
2734 verschachtelte Funktionsaufrufe später wusste ich zumindest,
was passiert:
Links baut sich beim einfachen, gemeinen Link, den ich anklicke, ein
neues URL, macht daraus sqrt(n) Funktionsaufrufe tiefer etwas der
Form "GET URL HTTP/1.0\nKopf" und ruft dann die Funktion auf,
die tatsaechlich die Netzwerkverbindung aufmacht und den fertigen
String dort hinschreibt, und dann die Funktion aufruft, die das
Erbebnis liest und irgendwas damit anstellt (Anzeigen, etc.).
Wie ist das bei Förmchen?
Die wurden irgendwann dazugebaut, und funktionieren genauso.
Das Form wird ausgewertet, die Parameter kodiert und ans URL
drangehängt, "PUT " davor- und "HTTP 1.0" dahintergekleibt, und oben
irgendwo wird eine funktion aufgerufen, die irgendeinen Kopf ggfls.
dahinterklebt, die Netzwerkverbindung aufmacht und das ganze dorthin
schreibt.
Wie ist das bei Förmchen mit File-Upload?
Die wurden irgendwann dazugebaut, und funktionieren genauso.
Das Form wird ausgewertet, die Parameter kodiert und ans URL
drangehängt, "PUT " davor- und "HTTP 1.0" dahintergekleibt, und oben
irgendwo wird eine funktion aufgerufen, die irgendeinen Kopf ggfls.
dahinterklebt, die Netzwerkverbindung aufmacht und das ganze dorthin
schreibt.
Nur, dass der Kopf jetzt einen Typen "multipart/mixed" hat", und noch
ein Body drangeklebt wird, der für jede Datei einen kurzkopf mit
"Content-Transfer-Encoding: base64" hat, auf den die Datei folgt.
Die Dateien werden dann schön stückweise eingelesen, ein Stueck
Speicher wird alloziiert, base64 da reinkodiert, an den restlichen
String drangehaengt nach realloc - oder gings direkt dahin? -
usw. Zum Schluss wird der String in die Netzwerkverbindung geschrieben,
dann das Resultat gelesen und dargestellt.
Es passen verdammt wenig Photos zu je 1.2 MB einschliesslich von
ein bis zwei Kopien ihrer Base64-Kodierung in den virtuellen
Adressraum, wenn man 64 MB RAM und 200 MB Swap-partitition hat.[3]
Eigentlich waere es trivial, dem ganzen Geraffel eine Art lazy evaluation
beizubringen, und in der Struktur um den String herum bloss mitzugeben,
welche Dateinamen es denn einlesen und base64kodieren soll, wenn die
der Netzwerkschreibaufruf mehr Daten will. Wenn ich mich nicht
sqrt(n) Funktionsaufrufe unterhalb von main() verlaufen hätte und keinen
Überblick mehr gehabt hätte, welche anderen N Funktionen noch auf
Datails dieser Struktur zugreifen.
Vielleicht sollte ich einfach schnell eine Vernünftige
Programmiersprache(tm) lernen und mir einen vernünftigen Browser
schreiben, dachte ich mir.
Es ging dann schneller, zum anderen Druckdienstleister zurückzukehren.
[1] Irgend'ne Notebookplatte in einem Shark[2]
[2] 233 MHz Strongarm SA-110, 64 MB RAM, PIO-IDE-Interface
[3] Der geneigte Leser mit 1 GB RAM mag sich einfach ein Profi-Digitalbackend
vorstellen, dass statt 3 Megapixel-JPEGs 12-Megapixel-RAW ausspuckt.
</Higgins>
--
seal your e-mail: http://www.gnupg.org/
Wieso? C++ ist doch eine super Anfängersprache um C zu lernen[1]. Wer
wirklich C++ will sollte stattdessen Haskell nehmen (was wiederum ein
super Einstieg ist um Scheme zu lernen...).
> Daher appelliere ich hiermit an die ganzen kranken Gestalten hier. Holt
> mal aus euren Giftschränken die Details raus und postet sie.
Ja mei, i hob vui Joahr long C++ propagiert, bis i endli C konnt. I
bin gheilt.
> Stichwörter bisher:
> - Namespaces, using-Deklarationen irgendwo ganz anders im Code.
Man kann in jeder Sprache unlesbaren Code schreiben. In C++ geht das
natürlich, dank der besonderen Unterstützung dafür, viel einfacher[2].
> Ich wollte [mich auch] über endlose Glue-Wrapper aufregen
Wrapper, das Äquivalent zur Substitutionsmethode der Mathematik, sind
hingegen aus Prinzip äußerst praktisch.
Grüße
- Robert Figura
[1]: Der Syntaktische Zucker führt letztlich zu Codebloat bis zur
Unlesbarkeit. Siehe $beliebiges_Projekt.
[2]: Ein kompetenter Entwickler läßt sich nicht qualitätserhaltend durch
einen miesen Entwickler ersetzen, selbst wenn dieser eine Sprache mit
Stützrädchen spricht.
--
[3]: Dies ist keine Fußnote
Ja, man nimmt einfach Data.Bytestring.Lazy und läßt den Rest des Codes
unverändert.
> Vielleicht sollte ich einfach schnell eine Vernünftige
> Programmiersprache(tm) lernen und mir einen vernünftigen Browser
> schreiben, dachte ich mir.
Exakt.
> Für einen demnächst zu haltenden Vortrag suche ich noch schlagkräftige
> Argumente, wieso C++ Scheiße ist.
Tja, ist eigentlich ganz einfach: Es gab schon vor 20 bis 30 Jahren gute
Entwicklungslösungen, und seitdem ist eigentlich nur noch das Rad immer
wieder neu erfunden worden (mal besser, mal schlechter). Es gibt
Programmiersprachen wie Pascal oder Basic (ernsthaft), mit denen sich
wunderschön strukturierter Code schreiben läßt, und Zugriff auf
Systemfunktionen ist mit entsprechenden Bibliotheken auch kein Problem.
Mit Basic meine ich übrigens nicht dieses Zeugs mit Zeilennummern und
GOTOs ohne Ende und auch nicht dieses obskure Zeugs von Microsoft, sondern
z.B. Freebasic und ähnliche Lösungen. Im Fall von Pascal gibt es
Freepascal (relativ mächtiger Compiler, Delphi-kompatibel, läuft auf
vielen Plattformen). Ein großer Schwachpunkt von C (und auch C++) ist, daß
ein Datentyp für Strings fehlt und man sich daher irgendwie behelfen muß.
Das führt dann häufig zu den bekannten Buffer-Overflows. Wer noch weitere
Argumente braucht: <http://www.bernd-leitenberger.de/pascal-und-c.shtml>
FreePascal: <http://www.freepascal.org>
FreeBasic: <http://www.freebasic-portal.de/>
Gruß,
Oliver
--
Ham Radio Station DL1YOV: http://www.mydarc.de/dl1yov
Ihr habt beide den Job.
Ich persönlich freue mich auf euer Perpetuum Mobile.
Wird bestimmt genau so ein Erfolg wie das, was sie da gerade in London
vorgestellt haben.
[etwas andere Reihenfolge des Quotings]
> Im Dritten geht es darum, welche Optimierungen man nicht im Quellcode
> durchführen soll, weil sie eh schon der Compiler für einen macht, und
> man die Sourcen nur weniger gut lesbar macht. Ist vielleicht auch für
> den einen oder anderen interessant, falls da jemand Ideen beisteuern
> will oder was zu zu sagen hat.
Passt doch eher fuer Java. Da wird oft an Stellen optimiert,
die der Hotspot zur Laufzeit meisst noch besser optimiert, als
man es durch Sourceoptimierung schafft oder absolut gesehen so
wenig im Vergleich zu Haemmern ein paar Zeilen weiter ergeben.
Von einem Freelancer habe ich mal folgendes bekommen:
----------------- schnipp
int i = 0;
try{
while(true){
arbeiteMitArrayElement(array[i++]);
}
}
catch(ArrayIndexOutOfBoundsException aioobe){}
----------------- schnapp
Nachdem der erste WTF-Moment verflogen war und rueckge-
fragt wurde, wurde als Grund genannt, das eine Ueber-
pruefung auf true schneller liefe als der Zugriff auf
das Laengenattribut eines Arrays und die Schleife damit
schneller liefe.
Mal von der Lesbarkeit abgesehen, hat man sich zu der Zeit,
als das geschrieben wurde (Java 1.1), leider nicht wirklich
viel eingespart, da das Erzeugen von Exceptions das so
ziemlich aufwendigste war, was es gab.
> PS: Das lief so. Ich habe zum CCC Camp drei Vorträge eingereicht.
> Einen wichtigen, coolen, über Integer Overflows, von dem ich mir sicher
> war, daß der genommen wird. Und zwei andere, die auch interessant sind,
> aber halt nicht so wichtig. Ich sagte ihnen, sie sollen einen
> auswählen, in der festen Annahme, daß es der Int Overflow Vortrag würde.
> Sie haben stattdessen die beiden anderen gewählt. Seufz.
Wahrscheinlich lief's so ab:
"He, der Felix hat Vortraege eingereicht"
"Wieviel sind es denn?"
"Drei."
"Was?! Hat der nix zu tun, oder was? Um was geht's denn bei den
Vortraegen?"
"Armageddon is near, Integer Overflows on the run"
"Wie jetzt? Sind ihm die bignums um die Ohren geflogen und will Trost?
Was noch?"
"C++ ist Scheisse."
"Das ist gut, das nehmen wir. Dann sparen wir uns statt dessen
den Vortrag 'Body Hacking, Part 2 - Praxis Workshop'"
"Und der dritte Vortrag ist ..."
"Will ich gar nicht wissen. Den hat er bestimmt eingereicht,
damit wir die anderen nehmen. Aergern wir ihn ein bisschen
und nehmen den auch noch."
Gruesse, Lothar
--
Lothar Kimmeringer E-Mail: spam...@kimmeringer.de
PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)
Always remember: The answer is forty-two, there can only be wrong
questions!
Felix von Leitner wrote:
> Thus spake Stefan Reuther (stefa...@arcor.de):
>>C++-spezifisch ist sowas wie
>> typ(foo[riesen_ausdruck])
>>Geht die Zeile z.B. mit '+3' weiter, wird da 'foo[riesen_ausdruck]' nach
>>'typ' gecastet und 3 addiert. Geht die Zeile mit ';' weiter, wird eine
>>neue Arrayvariable eingeführt.
>
> Das ist zwar widerlich, aber das kann man sich angewöhnen, und dann
> sieht man das mit einem Blick.
Du frugst nach Dingen, die eklig zu parsen sind, und sowas ist ächt[tm]
eklig zu parsen, mit "1 Token Lookahead" kommt man da lange nicht mehr hin.
> Ich meine so Sachen wie eine Codezeile,
> die völlig harmlos aussieht, aber bei näherer Betrachtung siehst du
> dann, daß du diese komplette Datei und fünfzehn andere Dateien komplett
> gelesen haben mußt, um diese eine Zeile verstehen zu können.
Man kann fast komplett neue Syntax erfinden. Zum Beispiel Boost.Lambda.
Sowas mit reinem Code-Studium zu erschließen, könnte schwierig werden.
Und dann gibt's noch benannte Infix-Operatoren a la Haskell:
Vector v, a, b;
v = a /vectorProduct/ b;
(Hint:
Closure operator/(const Vector&, Vector(*)(const Vector&,const Vector&));
Vector operator/(const Closure&, const Vector&);
)
> Ich habe da auch eine Entwicklung durchgemacht, und fand am Anfang z.B.
> Referenzen eine großartige Sache.
>
> Dann habe ich mich mal beim Code Lesen beobachtet. Durch C Code kann
> ich in nicht-pathologischen Fällen durchscrollen, dabei den Sinn
> mitnehmen, und gefährliche Stellen fallen mir auf. Das liegt u.a.
> daran, daß man bei
>
> d=foo(a,&b,c);
>
> erkennt, daß d und b geschrieben werden. Gut, man braucht immer noch
> Kontext, ob a und b Zeiger auf irgendwas sind. Aber bei C++ können
> plötzlich auch Skalare ohne & übergeben werden und dabei geschrieben
> werden. Das ist ein echter Nachteil.
Bei gutem Code erkennt man das am Namen der Funktion, und ist ansonsten
mit M-. sofort beim Funktionsprototypen. Dieses neumodische bunte
Klickzeug zeigt den Prototypen sogar in so lustigen Popups an.
Ja, mich hat das schon gestört, aber die Vorteile (eine Referenz kann
halt nicht NULL sein) überwiegen für mich.
Historisch war der Grund für die Einführung von Referenzen allerdings
nur, dass Bjarne für die Vektoraddition '&c = &a + &b;' schreiben wollte.
> Meine zentrale Kritik an C++ ist, daß da das Programmieren optimiert
> wird, nicht das Lesen und Warten des Codes. Dabei macht es nur 10-20%
> aus.
Das "Killerfeature" von C++ gegenüber den sogenannten C++-Nachfolgern
(Java, C#, D) ist IMHO das Vorhandensein von Headerfiles, was das Lesen
von Code sehr vereinfacht. Um Java-Code zu verstehen, darfst du erstmal
Javadoc drüberlaufen lassen.
Setzt natürlich voraus, dass der Entwickler halbwegs anständig
gearbeitet hat. Wir haben hier einen, der schreibt gerne
#pragma weak blafasel__FiiPc
void blafasel(int,int,const char*);
// ...
if (blafasel) blafasel(47,11,"fred");
Nach einem geeigneten LART wird noch gesucht.
>>> - Templates, partielle Spezialisierung
> Ich dachte eher an sowas wie daß jemand eine vorgeblich harmlose und
> bekannte STL-Funktion aufruft, aber deren Sinn durch eine fiese
> Spezialisierung anderswo komplett entstellt wird.
>
> Das wird zwar in normalem Code nicht passieren, aber als Code Auditor
> soll man ja gerade die ungewöhnlichen Fälle finden und kann daher nicht
> davon ausgehen, daß sie nicht vorkommen.
bool operator<(const A&, const A&) { return rand() & 1; }
dürfte eine std::map<A,int> recht verlässlich abschießen (mit dem
Äquivalent davon hab ich allerdings auch schon Solaris' qsort zerlegt).
A propos map: 'if (m[x] == 0)' legt dir selbstverständlich das Element
'x' in der map an, falls es noch nicht drin ist.
Auch schön ist die Tatsache, dass
assert(s[s.size()] == 0);
wohldefiniert gültig ist, falls s ein 'const std::string' ist, aber
undefiniertes Verhalten hat, falls es nicht konstant ist.
> Ich suche noch ein Beispiel für eine besonders perverse Fehlermeldung.
> Ich erinnere mich da an ganz furchtbare STL-Meldungen, aber gcc hat das
> ein bißchen umgestellt. Heute kriegt man statt einer Zeile der Länge
> 500 dann lieber 7 Zeilen mit jeweils 80 Zeichen.
*hass*.
-fmessage-length=0
Ansonsten hatte ich gegen böse Fehlermeldungen früher mal ein
Schnipselchen Lisp, das im *compilation* alle Vorkommen von
'std::basic_string<char, std::char_traits<char>, std::allocator<char> >'
(oder wie das Ding heißt) durch 'std::string' ersetzt und noch einige
mehr (und 'struct _IO_FILE' durch 'FILE').
>>Vor Urzeiten hatte ich mal den hier:
>> struct a{typedef int foo;};struct a1:a{};struct a2:a{};
>> #define X(b,a) struct a##1:b##1,b##2{};struct a##2:b##1,b##2{};
>> X(a,b)X(b,c)X(c,d)X(d,e)X(e,f)X(f,g)X(g,h)X(h,i)X(i,j)X(j,k)X(k,l)
>> X(l,m)X(m,n) n1::foo main(){}
>>an dem ein gcc 3.x eine halbe Stunde compiliert. Das baut eine hübsch
>>verschachtelte Klassenhierarchie auf, und der Compiler muss alle Pfade
>>prüfen, um 'n1::foo' aufzulösen. gcc verwendet einen O(4^n)-Algorithmus,
>>es ist aber auch wesentlich schneller zu schaffen.
>
> gcc braucht inzwischen ~ 90 Sekunden dafür.
...und größenordnungsmäßig >1 GB RAM, als ich das das letze Mal probiert
hab.
> Na die meisten Klassenbibliotheken haben virtuelle Funktionen. Und der
> Compiler muß dann eben Funktionen reinlinken, die nie aufgerufen werden,
> weil ein Zeiger in einer vtable auf sie verweist. So gerne wie die
> Leute da draußen Vererbung und virtuelle Funktionen verwenden, läßt sich
> das gar nicht verhindern in Programmen in der Praxis.
In der Praxis schreibt aber auch in C keiner außer Größenoptimierern
alle Funktionen in einzelne C-Dateien, um unreferenzierte Funktionen aus
dem Binary zu streichen. Wobei es Linker gibt, die zumindest sowas
auflösen können. Das Auflösen von vtbls ist zumindest prinzipiell
machbar, aber irgendwie scheint kein Leidensdruck da zu sein, dass das
mal jemand implementiert. Und meine Tage haben leider auch nur 24
Stunden, sonst wäre mein hübscher kleiner ELF-Linker schon viel weiter.
>>>Zuschriften gerne auch per Mail, aber ich vermute mal, die ganze Rotte
>>>hier würde sich über eine schöne C++-Schlammschlacht freuen.
>>
>>Letztenendes halte ich C++ immer noch für die am wenigsten stinkende
>>halbwegs portable ernsthafte Programmiersprache. Alles andere ist nur in
>>der Theorie portabel und/oder verfügbar.
>
> A...aber C#!1!! :-)
Portabel? Verfügbar?
Und das Referenzproblem hast du dort gleich doppelt.
Dings a = b;
a.fred = 1;
Falls 'Dings' ein 'struct' ist, änderst du a's eigene Kopie. Ist es ein
'class', änderst du b gleich mit. Du darfst also nicht nur die
Definition der Variablen anschauen, sondern die des Typs gleich mit. OK,
kannst du in C++ mit 'typedef Bums& Dings' auch haben, allerdings hab
ich das in freier Wildbahn noch nicht gesehen.
> Im Dritten geht es darum, welche Optimierungen man nicht im Quellcode
> durchführen soll, weil sie eh schon der Compiler für einen macht, und
> man die Sourcen nur weniger gut lesbar macht. Ist vielleicht auch für
> den einen oder anderen interessant, falls da jemand Ideen beisteuern
> will oder was zu zu sagen hat.
In der Praxis hab ich hier drei Compiler, die bei meinen DSP-Kram Code
mit Laufzeitunterschieden von Faktor 10 und mehr auseinander generieren.
Und selbst beim schnellsten davon bringt Schleifen aufrollen noch was,
weil der nicht von selbst auf die Idee kommt, bei einem 10-tap-FIR das
Array mit den 10 Speichergliedern in 10 Registern zu parken.
Das wichtigste ist vor allem, den unoptimierten Code stehen zu lassen,
falls er mal in eine andere Richtung optimiert werden soll - oder
einfach nur verstanden werden will. Das wird oft und gerne vergessen.
Stefan
Als ich das das letzte mal implementiert habe, habe ich auf die harte
Tour gelernt, dass die Gegenstelle beim Form-Upload kein base64
verträgt. Laut Aussage des Betreibers ist das CGI.pm. Ergo durfte ich
mich dann damit rumschlagen, wie man anständige Multipart-Boundaries in
einen Binärstrom reinfummelt.
> Eigentlich waere es trivial, dem ganzen Geraffel eine Art lazy evaluation
> beizubringen, und in der Struktur um den String herum bloss mitzugeben,
> welche Dateinamen es denn einlesen und base64kodieren soll, wenn die
> der Netzwerkschreibaufruf mehr Daten will.
UI: Der Server möchte gerne im Header die Größe des Requests haben
("HTTP/1.0 requests containing an entity body must include a valid
Content-Length header field."). Wenn man sich nicht allerlei Races
einfangen will (z.B. während des Postens der Datei über ein 64kbit-
Link kürzt jemand parallel dazu die Datei ein), baut man den Request
vorher komplett zusammen und zählt durch.
Stefan
> Muß es C++ sein oder reichen auch Objekte aus C-structs? Ich versuche
> gerade PETSc (http://www-unix.mcs.anl.gov/petsc) mit
> intel-C/C++/Fortran 10.0 zu übersetzen und wundere mich, warum das
> icc-Backend die 4GB RAM vollaufen läßt bis nichts mehr geht -- mit
> intel 9.1 hatte doch schließlich auch alles funktioniert. Also mal
> schnell in den Code geschaut, was los ist... Meine Omma hat immer
> gesagt "Im Krankenhaus hamse den Erwin aufgeschnitten und gleich
> wieder zugemacht."
Nachdem ich mit PETSc in naher Zukunft zu tun haben werde und die
Update-Beschaffung der Intel-Compiler ebenfalls ansteht, würd's mich
freuen, wenn du ein bißchen was zu den Problemen sagen könntest!
Sebastian
Ein großer Schwachpunkt von Leuten, die ihre Lieblingssprache mit C
vergleichen, ist, daß sie C nicht verstanden haben. An dieser Stelle
habe ich aufgehört zu lesen:
|char * StringToUpper(char * zeile)
|{
| char * temp;
| int i;
| int p = strlen(zeile);
| temp = (char *) malloc(p);
| for (i=0; zeile[i]!=0 && i<256; i++)
| if (zeile[i]>='a' && zeile[i]<='z')
| temp[i]=(char) zeile[i]-32; else temp[i]=zeile[i];
| temp[i]=0;
| return temp;
|}
Vom grausamen Stil abgesehen (niemand, der C kann, programmiert so),
produziert dieser Code einen netten Off-By-One-Buffer-Overflow.
Ein Bernd Leitenberger, der schon bei so trivialen Codebeispielen
versagt, sollte sich tatsächlich von C fernhalten.
ciao, Joseph
[C-Beispiel]
> Vom grausamen Stil abgesehen (niemand, der C kann, programmiert so),
> produziert dieser Code einen netten Off-By-One-Buffer-Overflow.
Das ist das Problem von Leuten, die Programmiersprachen verwenden,
wo man sich nicht so nah auf Speicherebene herumtreibt. Geht mir
aehnlich, wenn ich wieder etwas in C machen muss, weil ich auf
Systemressourcen von Java aus zugreifen "darf".
> Ein Bernd Leitenberger, der schon bei so trivialen Codebeispielen
> versagt, sollte sich tatsächlich von C fernhalten.
Es gibt da noch andere Beispiele:
| Warum man mit == und != vergleicht anstatt
| mit = und <> habe ich auch nie verstanden.
Ich habe es lange Zeit genau anders herum nicht verstanden, warum
<> als ungleich verwendet wird, da man das als "kleiner und groesser"
lesen kann und damit nie zutreffen wird.
Und dann noch:
| Die Logik bei der Repeat...Until Schleife ist bei C umgedreht:
|
| Anstatt
|
| Repeat....UNTIL Bedingung erfüllt heißt es:
|
| do... while Bedingung nicht erfüllt.
Sogar umgangssprachlich ist der Unterschied klar. "Mache, bis ... ist"
und "Mache, solange ... ist"
Und final:
| int x;
| x=5;
| --x=(++x)--;
|
| Nein, das Ergebnis ist nicht 4 sondern 6.
Wer sowas ernsthaft in einem Programm schreibt, gehoert sowieso
erschlagen, egal in welcher Sprache das passiert ;-)
A!S
--
Wenn ich in der Jugend jemand seine Nase mit Geräusch reinigen sah,
hoffte ich es einst auch tun zu können und beneidete ihn.
-- Jean Paul
A!S
--
In der Kirche singen immer die am lautesten, die falsch singen.
-- Franz Grillparzer
> Blöd nur, dass die Prüfung der IDE das anmeckert, weil die Parameter
> *eigentlich* ja ganz anders heißen. So kommt man dann zu Code mit
> 8000 Warnings. Von den Methoden ganz ohne Javadoc gar nicht erst zu
> sprechen.
Toll ist dann auch, wenn sich drei Klassen ploetzlich im Repository
aendern, weil besagter Entwickler dann einen unbenutzten import
herausloescht, weil ihm das die IDE als Warnung anzeigt, waehrend
man selbst am rechten Rand einen schoenen gelben Strich stehen hat
(bis auf ganz oben ein halber Millimeter).
Ha, fiel mir doch mein Lieblingsfehler wieder ein:
#include <fstream>
class Dings : public std::ofstream {
public:
Dings()
: std::ofstream("/dev/tty")
{ }
Dings& self()
{ return *this; }
};
int main() {
Dings() << "hi there\n";
Dings().self() << "hi there\n";
}
('Dings' ist bei mir z.B. ein std::stringstream-Wrapper, der im
Destruktor eine Messagebox anzeigt, oder was in der Art. Gehässigerweise
funktioniert das auf einigen Compilern wie vermutet; normkonforme
Compiler geben bei der ersten <<-Zeile einen Zeiger aus.)
Stefan
Das könnte man dann als Unterlage für die Emacs-Referenztasse (ihr wisst
schon, die, die man bei Regen als Unterstand benutzen kann) verwenden.
Stefan
Ich weiß ja nicht, welchen C++-Compiler du so verwendest, aber bei
allen, die ich in den letzten 10 Jahren benutzt habe, war eine sehr
brauchbare Stringklasse dabei.
Die erweiterten Pascals sind zwar schön, aber leider in der Praxis
einfach nicht portabel: wenn man dann schon mal einen Compiler für den
gewählten Dialekt gefunden hat, gibt's den unter Garantie nicht für die
Zielplattform.
Stefan
A!S
--
Der Zorn beginnt mit Wut und schließt mit Reue.
-- Publilius Syrus (1. Jh. v. Chr.)
Nein.
Ich will zeigen, daß C++ auch dann Scheiße ist, wenn du alles weißt und
alles richtig machst. Daher geht es mir nicht so um "ich kann
programmieren und soll programmieren" sondern um "ich kann programmieren
und soll diesen Code hier lesen".
Felix
> Ich will zeigen, daß C++ auch dann Scheiße ist, wenn du alles weißt und
> alles richtig machst. Daher geht es mir nicht so um "ich kann
> programmieren und soll programmieren" sondern um "ich kann programmieren
> und soll diesen Code hier lesen".
>
Der Inhalt wäre Seitenfüllend "Let it be!"
A!S
--
Wenn Microsoft Autos bauen würde ...
würde beim Versuch, das Auto zu starten, oft die Fehlermeldung:
"Abbruch, Wiederholen, Ignorieren" erscheinen.
Ich stimme zu, C++ Parsen ist ein hartes Problem.
Aber als Mensch hat man mehr als ein Token Lookahead.
> > Ich meine so Sachen wie eine Codezeile,
> > die völlig harmlos aussieht, aber bei näherer Betrachtung siehst du
> > dann, daß du diese komplette Datei und fünfzehn andere Dateien komplett
> > gelesen haben mußt, um diese eine Zeile verstehen zu können.
> Man kann fast komplett neue Syntax erfinden. Zum Beispiel Boost.Lambda.
> Sowas mit reinem Code-Studium zu erschließen, könnte schwierig werden.
Au weia, das hab ich noch gar nicht wahr genommen.
Danke für den Hinweis!
> Und dann gibt's noch benannte Infix-Operatoren a la Haskell:
> Vector v, a, b;
> v = a /vectorProduct/ b;
Oh Graus!
> > erkennt, daß d und b geschrieben werden. Gut, man braucht immer noch
> > Kontext, ob a und b Zeiger auf irgendwas sind. Aber bei C++ können
> > plötzlich auch Skalare ohne & übergeben werden und dabei geschrieben
> > werden. Das ist ein echter Nachteil.
> Bei gutem Code erkennt man das am Namen der Funktion, und ist ansonsten
> mit M-. sofort beim Funktionsprototypen. Dieses neumodische bunte
> Klickzeug zeigt den Prototypen sogar in so lustigen Popups an.
Du kannst eben nicht von gutem Code ausgehen. Ich schrecke auch nicht
davor zurück, von bösartigem Code auszugehen, um meinen Punkt zu
demonstrieren.
Daß man vieles davon mit Tools lösen kann, bestreite ich nicht.
Allerdings haben wir ja gesehen, wie schwierig es ist, einen korrekten
Parser für C++ zu schreiben. Mein Vertrauen in irgendwelche Tools ist
da auch eher gering. Kollegen von mir setzen z.B. gerne "Source
Insight" ein zum Codelesen. Ich nicht. Ich habe schon diverse "öh, den
Code hier kann ich nicht parsen" Fehlermeldungen und sogar Abstürze
davon gesehen.
Daher ist das in meinen Augen ein schwerer Nachteil, wenn man tolle
Tools braucht, um dem Code folgen zu können.
> Ja, mich hat das schon gestört, aber die Vorteile (eine Referenz kann
> halt nicht NULL sein) überwiegen für mich.
Eine Referenz kann trotzdem z.B. auf zwischenzeitlich freigegebenen
Speicherplatz verweisen oder so. Insofern hilft das nur auf dem Papier.
> Historisch war der Grund für die Einführung von Referenzen allerdings
> nur, dass Bjarne für die Vektoraddition '&c = &a + &b;' schreiben wollte.
Ich las, es ging darum, daß eine Funktion ein lvalue zurück geben können
sollte. Am Ende für c = a + b, ja.
> Das "Killerfeature" von C++ gegenüber den sogenannten C++-Nachfolgern
> (Java, C#, D) ist IMHO das Vorhandensein von Headerfiles, was das Lesen
> von Code sehr vereinfacht. Um Java-Code zu verstehen, darfst du erstmal
> Javadoc drüberlaufen lassen.
Ich habe Probleme damit, wenn unter einem Namen n Funktionen existieren.
Ja, wenn ich den Code schreibe, dann erscheint mir das auch nützlich,
weil ich das dann so mache, daß alle Instanzen das selbe tun, aber davon
kannst du ja beim Lesen von anderer Leute Code nicht ausgehen.
> Setzt natürlich voraus, dass der Entwickler halbwegs anständig
> gearbeitet hat. Wir haben hier einen, der schreibt gerne
> #pragma weak blafasel__FiiPc
> void blafasel(int,int,const char*);
> // ...
> if (blafasel) blafasel(47,11,"fred");
> Nach einem geeigneten LART wird noch gesucht.
Ach du meine Güte!
> >>> - Templates, partielle Spezialisierung
> > Ich dachte eher an sowas wie daß jemand eine vorgeblich harmlose und
> > bekannte STL-Funktion aufruft, aber deren Sinn durch eine fiese
> > Spezialisierung anderswo komplett entstellt wird.
> >
> > Das wird zwar in normalem Code nicht passieren, aber als Code Auditor
> > soll man ja gerade die ungewöhnlichen Fälle finden und kann daher nicht
> > davon ausgehen, daß sie nicht vorkommen.
> bool operator<(const A&, const A&) { return rand() & 1; }
> dürfte eine std::map<A,int> recht verlässlich abschießen (mit dem
> Äquivalent davon hab ich allerdings auch schon Solaris' qsort zerlegt).
Ja, so ähnlich. Aber das finde ich "zu einfach", weil es operator
overloading beinhaltet. Das ist ja schon fast ein Klischee, auf
operator overloading rumzuhauen.
> A propos map: 'if (m[x] == 0)' legt dir selbstverständlich das Element
> 'x' in der map an, falls es noch nicht drin ist.
Natürlich.
Ich finde es ja grandios, daß operator[] bei einem std::vector kein
range check macht, und man dafür at() nehmen muß. Was geht denn bitte
in solchen Leuten vor?!
> Auch schön ist die Tatsache, dass
> assert(s[s.size()] == 0);
> wohldefiniert gültig ist, falls s ein 'const std::string' ist, aber
> undefiniertes Verhalten hat, falls es nicht konstant ist.
Ach? -v?
> > Ich suche noch ein Beispiel für eine besonders perverse Fehlermeldung.
> > Ich erinnere mich da an ganz furchtbare STL-Meldungen, aber gcc hat das
> > ein bißchen umgestellt. Heute kriegt man statt einer Zeile der Länge
> > 500 dann lieber 7 Zeilen mit jeweils 80 Zeichen.
> *hass*.
> -fmessage-length=0
> Ansonsten hatte ich gegen böse Fehlermeldungen früher mal ein
> Schnipselchen Lisp, das im *compilation* alle Vorkommen von
> 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >'
> (oder wie das Ding heißt) durch 'std::string' ersetzt und noch einige
> mehr (und 'struct _IO_FILE' durch 'FILE').
HAHAHAHA, und mit sowas verbringt man dann seine Zeit. Zum Kotzen.
> >>Vor Urzeiten hatte ich mal den hier:
> >> struct a{typedef int foo;};struct a1:a{};struct a2:a{};
> >> #define X(b,a) struct a##1:b##1,b##2{};struct a##2:b##1,b##2{};
> >> X(a,b)X(b,c)X(c,d)X(d,e)X(e,f)X(f,g)X(g,h)X(h,i)X(i,j)X(j,k)X(k,l)
> >> X(l,m)X(m,n) n1::foo main(){}
> >>an dem ein gcc 3.x eine halbe Stunde compiliert. Das baut eine hübsch
> >>verschachtelte Klassenhierarchie auf, und der Compiler muss alle Pfade
> >>prüfen, um 'n1::foo' aufzulösen. gcc verwendet einen O(4^n)-Algorithmus,
> >>es ist aber auch wesentlich schneller zu schaffen.
> > gcc braucht inzwischen ~ 90 Sekunden dafür.
> ...und größenordnungsmäßig >1 GB RAM, als ich das das letze Mal probiert
> hab.
Mhh, nee, haben sie offenbar gefixt. Ich verwende gcc 4.2 auf amd64,
und da braucht der 30 MB.
> Und meine Tage haben leider auch nur 24 Stunden, sonst wäre mein
> hübscher kleiner ELF-Linker schon viel weiter.
Wo kann man sich denn den Zwischenstand mal angucken?
> OK, kannst du in C++ mit 'typedef Bums& Dings' auch haben, allerdings
> hab ich das in freier Wildbahn noch nicht gesehen.
Guter Punkt! *notier*
> > Im Dritten geht es darum, welche Optimierungen man nicht im Quellcode
> > durchführen soll, weil sie eh schon der Compiler für einen macht, und
> > man die Sourcen nur weniger gut lesbar macht. Ist vielleicht auch für
> > den einen oder anderen interessant, falls da jemand Ideen beisteuern
> > will oder was zu zu sagen hat.
> In der Praxis hab ich hier drei Compiler, die bei meinen DSP-Kram Code
> mit Laufzeitunterschieden von Faktor 10 und mehr auseinander generieren.
> Und selbst beim schnellsten davon bringt Schleifen aufrollen noch was,
> weil der nicht von selbst auf die Idee kommt, bei einem 10-tap-FIR das
> Array mit den 10 Speichergliedern in 10 Registern zu parken.
Ja, das werde ich auch erwähnen. Manche Sachen bringen was. Unrolling
z.B.
Aber was so gut wie nirgends was bringt ist das Umstellen von
indexbasiertem Arrayzugriff auf Zeigerarithmetik. Oder manuelle
Strength Reduction. Umstellen von x/4 auf x>>2. Sowas.
> Das wichtigste ist vor allem, den unoptimierten Code stehen zu lassen,
> falls er mal in eine andere Richtung optimiert werden soll - oder
> einfach nur verstanden werden will. Das wird oft und gerne vergessen.
ACK!
Felix
Jetzt mußte ich doch mal kurz nach transbuf greppen gerade *hust*
Felix
> Ich weiß ja nicht, welchen C++-Compiler du so verwendest, aber bei
> allen, die ich in den letzten 10 Jahren benutzt habe, war eine sehr
> brauchbare Stringklasse dabei.
>
Tja, nur die Frage ist, ob diese Klassen zum Standard gehören. Es wird
zwar immer gesagt, C und C++ wären äußerst portabel, aber das gilt nur für
relativ wenige Programme. Sobald es ein wenig komplexer wird, mit Grafik,
GUI etc. ist es mit der Portabilität schon vorbei. Selbst so vermeintlich
triviale Sachen wie die Abfrage der Tastatur sind schon nicht mehr
betriebssystemunabhängig.
> Die erweiterten Pascals sind zwar schön, aber
>leider in der Praxis
> einfach nicht portabel: wenn man dann schon mal einen Compiler für den
> gewählten Dialekt gefunden hat, gibt's den unter Garantie nicht für die
> Zielplattform.
>
FreePascal läuft mittlerweile auf einer recht großen Anzahl von
Plattformen, siehe <http://www.freepascal.org>, von GNU Pascal mal ganz zu
schweigen. Und sowohl FreePascal wie auch FreeBasic bieten mittlerweile
Features wie Objektorientierung, Zeiger, Enums usw., so daß man C bzw. C++
eigentlich kaum noch vermißt.
>>Daher geht es mir nicht so um "ich kann
>>programmieren und soll programmieren" sondern um "ich kann programmieren
>>und soll diesen Code hier lesen".
> Fremden Code lesen zu müssen ist eine der beschissensten Aufgaben, die
> man sich antun kann ;-) Allerdings ist es ab und zu auch interessant, die
> niedergeschriebenen Hirnwindungen der Kollegen zu lesen.
Nunja, bei $ORKPLACE kriegst Du keinen Code mehr in Produktion, den
nicht irgend jemand gelesen und für gut befunden hat.
Wobei, so richtig interessant wäre eine Produktionslinie, in der
Entwickler A den Algorithmus in sagen wir mal Haskell formulieren muß,
Entwickler B dann aus diesem Haskell-Code ohne Kenntnis des
Pflichten-/Lastenhefts sagen wir mal Pascal machen muß und dann Revisor
C den Pascal-Code formal gegen das Pflichtenheft vergleicht :-)
--
Erhard Schwenk
Akkordeonjugend Baden-Württemberg - http://www.akkordeonjugend.de/
APAYA running System - http://www.apaya.net/
Das ist kein Grund, den Rückgabewert von malloc() zu casten. ;-)
>> Ein Bernd Leitenberger, der schon bei so trivialen Codebeispielen
>> versagt, sollte sich tatsächlich von C fernhalten.
>
> Es gibt da noch andere Beispiele:
>
>| Warum man mit == und != vergleicht anstatt
>| mit = und <> habe ich auch nie verstanden.
>
> Ich habe es lange Zeit genau anders herum nicht verstanden, warum
><> als ungleich verwendet wird, da man das als "kleiner und groesser"
> lesen kann und damit nie zutreffen wird.
Eher »kleiner _oder_ größer« analog zu >=. Aber wenn man ! (not) und ==
(gleich) kennt, erschließt sich einem die Bedeutung von != von selbst.
> Und final:
>
>| int x;
>| x=5;
>| --x=(++x)--;
>|
>| Nein, das Ergebnis ist nicht 4 sondern 6.
Nein, das kompiliert schlicht nicht:
|test.c:5: error: invalid lvalue in decrement
> Wer sowas ernsthaft in einem Programm schreibt, gehoert sowieso
> erschlagen, egal in welcher Sprache das passiert ;-)
ACK.
ciao, Joseph
> Wobei, so richtig interessant wäre eine Produktionslinie, in der
> Entwickler A den Algorithmus in sagen wir mal Haskell formulieren muß,
> Entwickler B dann aus diesem Haskell-Code ohne Kenntnis des
> Pflichten-/Lastenhefts sagen wir mal Pascal machen muß und dann Revisor
> C den Pascal-Code formal gegen das Pflichtenheft vergleicht :-)
Ah, Stille Post!
> Tja, nur die Frage ist, ob diese Klassen zum Standard gehören. Es wird
> zwar immer gesagt, C und C++ wären äußerst portabel, aber das gilt nur für
> relativ wenige Programme.
Ach was,
Boost, Qt & Smartheap gibt's fast überall :)
> FreePascal läuft mittlerweile auf einer recht großen Anzahl von
> Plattformen, siehe <http://www.freepascal.org>, von GNU Pascal mal ganz zu
> schweigen.
Wie war das mit der GUI nochmal?
Gruß Carsten
--
0x2BFBF5D8 FP = 53CA 1609 B00A D2DB A066 314C 6493 69AB 2BFB F5D8
http://www.realname-diskussion.info - Realnames sind keine Pflicht
http://www.spamgourmet.com/ + http://www.temporaryinbox.com/ - Antispam
cakruege (at) gmail (dot) com | http://www.geocities.com/mungfaq/
Klar, entspricht nicht dem 'strick weak ordering' welches std::map & Co
voraussetzen. Sowas wird allerdings von aktuellen Implementierungen durch
spezielle Debug-Checks detektiert, also wenn Du beim Debuggen durch den
Pfad durchkommst hast Du gute Chancen dass Dir das Programm kontrolliert um
die Ohren fliegt.
> Ja, so ähnlich. Aber das finde ich "zu einfach", weil es operator
> overloading beinhaltet. Das ist ja schon fast ein Klischee, auf
> operator overloading rumzuhauen.
Ist doch garnicht so schlimm, wenn man sich erstmal daran gewoehnt hat. Ich
zumindest kenne das in etwa seit der zweiten Klasse in der Schule, wenn
auch zugegebenermassen nicht unter diesem Namen.
> Ich finde es ja grandios, daß operator[] bei einem std::vector kein
> range check macht, und man dafür at() nehmen muß. Was geht denn bitte
> in solchen Leuten vor?!
Kannst Du ganz einfach nachlesen, ueber Alex Stepanov (sp?) gibt es viele
interessante Infos im Netz. Kurz, der Grund ist Performance. Eine einfache
for-Schleife ueber einen vector zu vergeigen ist auch einfach zu
unwahrscheinlich als dass ich auch nur einen Taktzyklus dafuer opfern
wuerde. Ansonsten gilt natuerlich dass selbe wie bei dem Komparator fuer
std::map, moderne Implementierungen fangen sowas im Debug-Modus ab.
>> Auch schön ist die Tatsache, dass
>> assert(s[s.size()] == 0);
>> wohldefiniert gültig ist, falls s ein 'const std::string' ist, aber
>> undefiniertes Verhalten hat, falls es nicht konstant ist.
>
> Ach? -v?
Du hast in basic_string<>:
char& operator[]( size_type n);
char const& operator[]( size_type n) const;
also einen ueberladenen Operator fuer konstante und nicht-konstante Objekte.
1. Wenn moeglich, wird immer der nicht-konstante aufgerufen.
2. Der konstante hat (wohl um als Ersatz fuer einen C-String dienen zu
koennen) noch diesen zusaetzlichen Terminator der an Index=Laenge steht und
auf den man zugreifen darf, waehrend der nicht-konstante das nicht hat. An
dieser Stelle verweist der Standard auch auf etwas
namens 'char_traits::eos', also ein End-Of-String, welches aber im ganzen
Standard nicht wieder erwaehnt wird. Das ist ein bekannter Fehler im
Standard.
Das Problem im obigen Stueck Code ist dass seine Gueltigkeit davon abhaengt
ob auf 's' schreibend zugegriffen werden kann, was in der Tat verwirrend
ist.
Uli
> Thus spake Christoph Kliemt (ne...@pgxml.net): > Geh draussen spielen.
>
> Wer hat denn dieses Kleinkind hier reingelassen, ohne ihm Respekt vor
> in Würde ergrauten Regulars zu vermitteln?
Für eine geeignete Definition von "Respekt"... wiauchimmer. ;-)
Nur mal so aus Interesse: Existiert eine Sprache die *nicht* eines
solchen Threads ("Wieso ist $SPRACHE eigentlich so schlecht?") wuerdig
ist?
Gruss Christoph
A!S
--
Ich habe etliche mal bemerkt, daß ich Kopf-Weh bekam, wenn ich mich
lange in einem Hohl-Spiegel betrachtete.
-- Georg Christoph Lichtenberg
>>| int x;
>>| x=5;
>>| --x=(++x)--;
>>|
>>| Nein, das Ergebnis ist nicht 4 sondern 6.
>
> Nein, das kompiliert schlicht nicht:
>
>|test.c:5: error: invalid lvalue in decrement
Inzwischen. Fruehere gcc-Versionen haben sowas gefressen.
Daher findet man manchmal auch so etwas wie
(jbyte *)jap = env->GetByteArrayElements(ja, 0);
das man dann entsprechend umbauen darf (hatte ich erst
kuerzlich, das Beispiel ist aus der vorigen Revision kopiert).
> Nur mal so aus Interesse: Existiert eine Sprache die *nicht* eines
> solchen Threads ("Wieso ist $SPRACHE eigentlich so schlecht?") wuerdig
> ist?
Jede Sprache hat ihre Grenzen. Wird sie von einer breiteren
Masse genutzt, ergibt sich automatisch Gemeckere.
Italienisch. Schönste Sprache der Welt. Alleine die Speisekarte hört
sich an wie eine Arie.
Gruß
Roger Schwentker
r.schw...@regioconnect.net
--
Wenn der Umsatz stimmt, ist Toleranz kein Problem. [Jürgen Becker]
> On Fri, 06 Jul 2007 10:55:54 +0000, Felix von Leitner wrote:
> [...]
>> Ich habe das Argument gehört (ernsthaft vorgetragen!), daß C++ ALLE
>> Funktionen virtual machen sollte, weil die verlorene CPU-Zeit billiger
>> sei als die Zeit der Programmierer für das Nachtragen der vergessenen
>> virtual Deklarationen.
>
> Das ist dann in Java "gefixt" worden.
Nee. Der default ist ein anderer.
> Moin,
>
> Felix von Leitner <usenet-...@fefe.de> writes:
>
>> Wer hat denn dieses Kleinkind hier reingelassen, ohne ihm Respekt vor
>> in Würde ergrauten Regulars zu vermitteln?
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^
> also für manchen Kommentar möchtest du da drüber nochmal nachdenken. Vor
> allem in diesem Thread.
Felix schrieb von "ergraut", nicht von "weise" ;-).
> Für einen demnächst zu haltenden Vortrag suche ich noch schlagkräftige
> Argumente, wieso C++ Scheiße ist.
Die kanonische Antwort ist doch eigentlich daß ein Makroassembler der ein paar
Hochsprachenkurse besucht hat und jetzt auch ganz doll oo kann Scheiße sein
muß, oder?
> Die konkrete Vortragsidee war, ein
> Stück Code zu haben, im Moment arbeite ich gedanklich mit
>
> baz = foo->bar(3);
>
> und dann zu zeigen, was es alles für mögliche Kontexte gibt, die man
> beachten muß, um sich sicher zu sein, daß man versteht, was dieses Zeile
> da eigentlich genau tut.
Inwiefern ist dasein Problem von C++? Bzw. mir erschließt sich gerade nicht,
inwiefern ein <java>baz = foo.bar(3)</> weniger komplex sein sollte (wenn man
mal von der leicht abstrahierten Speicherverwaltung absieht.
> Ich will hauptsächlich darauf abheben, daß einem jemand ein an
> kompilierendes und linkendes Codestück gibt, aber man exorbitant Kontext
> braucht, um a) das parsen und b) erklären zu können, was dieser Code
> tut.
Zeige mir eine Sprache, die dergleichen nicht erfordert.
> Daher appelliere ich hiermit an die ganzen kranken Gestalten hier. Holt
> mal aus euren Giftschränken die Details raus und postet sie.
Gut, C++ ist schon ausgesprochen hässlich.
> Ich wollte auch auf vtable-Bloat eingehen, und mich über endlose
> Glue-Wrapper aufregen, aber das ist eher Randprogramm. In der
> Hauptsache soll es darum gehen, daß es fast unmöglich ist, ein kleines
> Stück C++-Code außerhalb der gesamten Kompilationseinheit zu betrachten.
Eh? Das ist letzten Endes bei allen seiteneffektigen Sprachen so.
> Zuschriften gerne auch per Mail, aber ich vermute mal, die ganze Rotte
> hier würde sich über eine schöne C++-Schlammschlacht freuen.
Kannst Du den Vortrag irgendwann ins Netz hängen?
Kein Importkonzept zu haben halte ich kaum für ein Feature.
> A propos map: 'if (m[x] == 0)' legt dir selbstverständlich das Element
> 'x' in der map an, falls es noch nicht drin ist.
Dafür gibt's find().
> >>Letztenendes halte ich C++ immer noch für die am wenigsten stinkende
> >>halbwegs portable ernsthafte Programmiersprache. Alles andere ist nur in
> >>der Theorie portabel und/oder verfügbar.
> > A...aber C#!1!! :-)
> Portabel? Verfügbar?
Portabel und verfügbar. Und Scheisse.
Felix, vielleicht möchtest Du zudem auch noch
http://david.tribble.com/text/cdiffs.htm
sowie
http://blog.copton.net/archives/cat_5/
lesen.
Viele Grüsse,
VB.
--
"Es muss darauf geachtet werden, dass das Grundgesetz nicht mit Methoden
geschützt wird, die seinem Ziel und seinem Geist zuwider sind."
Gustav Heinemann, "Freimütige Kritik und demokratischer Rechtsstaat"
Selbstverständlich.
> Es wird zwar immer gesagt, C und C++ wären äußerst portabel, aber das
> gilt nur für relativ wenige Programme.
Interessanterweise kann man damit aber noch sehr viel machen. Einen
C-Compiler schreiben zum Beispiel. Oder einen MPEG-Decoder. Oder einen
großen Teil der Unix-Kommandozeilentools (grep, cat, ...). Und die kann
man dann mit den verschiedensten Compilern übersetzen. Meine Hobby-
Projekte übersetze ich routinemäßig mit drei verschiedenen Compilern
(GNU, Turbo C, Borland C++). Die, mit denen ich Geld verdiene, mit vier
verschiedenen (GNU, MSVC, sowie zwei für Embedded-Plattformen).
> Sobald es ein wenig komplexer wird, mit Grafik, GUI etc. ist es mit der
> Portabilität schon vorbei. Selbst so vermeintlich triviale Sachen wie
> die Abfrage der Tastatur sind schon nicht mehr betriebssystemunabhängig.
Was daran liegt, dass es sowas wie eine Tastatur portabel nicht gibt.
Die Tastatur meiner Zielhardware hat 13 Tasten und zwei Drehencoder.
Dennoch läuft da der gleiche MPEG-Codec, den ich auf dem PC getestet habe.
GUI hast du nur in Sprachen, die sich auf eine Plattform festlegen.
Entweder eine native Plattform (MFC -> Win32), oder eine emulierte
solche (Java).
Stefan
> | Warum man mit == und != vergleicht anstatt
> | mit = und <> habe ich auch nie verstanden.
>
> Ich habe es lange Zeit genau anders herum nicht verstanden, warum
> <> als ungleich verwendet wird, da man das als "kleiner und groesser"
> lesen kann und damit nie zutreffen wird.
Und "=" kann man als Minus-Minus lesen, also als Plus. == ist damit ++, also
ein Inkrement!!! Und "!=" ist besonders plus.
--
A bone to the dog is not charity. Charity is the bone shared with the dog, when
you are just as hungry as the dog.
-- Jack London
Friß, Spammer: bjha...@fUw4ux.7eggert.dyndns.org Lr1....@7eggert.dyndns.org
Neinein! Das ist das Gegenteil einer Zuweisung, also eine wo l-value und
r-value vertauscht sind. Mir kommen grade ein paar echt perfide Ideen, aber
andererseits koennte ich auch gleich Perl nehmen...
Blödsinn. Denn: der Compiler optimiert das raus.
Beispiel-Code zum selber gucken:
for (i=0; i<20; ++i) {
if (i<100) // immer wahr, erzeugt keinen Code
printf("i=%d\n",i);
}
Da wir es hier mit einer Template-Bibliothek zu tun haben, liegen auch
konkrete Werte vor, und der Compiler kann redundante Range Checks
entfernen.
> >> Auch sch?n ist die Tatsache, dass
> >> assert(s[s.size()] == 0);
> >> wohldefiniert g?ltig ist, falls s ein 'const std::string' ist, aber
> >> undefiniertes Verhalten hat, falls es nicht konstant ist.
> > Ach? -v?
> Du hast in basic_string<>:
> char& operator[]( size_type n);
> char const& operator[]( size_type n) const;
> also einen ueberladenen Operator fuer konstante und nicht-konstante Objekte.
> 1. Wenn moeglich, wird immer der nicht-konstante aufgerufen.
Wie auch in diesem Fall, unabhängig davon ob s jetzt lesbar ist oder
nicht, denn der konkrete Zugriff ist lesend.
> Das Problem im obigen Stueck Code ist dass seine Gueltigkeit davon abhaengt
> ob auf 's' schreibend zugegriffen werden kann, was in der Tat verwirrend
> ist.
Mein Verständnis ist bisher, daß immer der const Operator genommen wird,
solange man darauf nur lesend zugreift. Ob das Objekt selber auch
schreibbar gewesen wäre, spielt keine Rolle.
Felix
Wo steht denn, daß ich Java für besser als C++ halte?
Erstens ist Java so offensichtlich scheiße, daß ich da keinen Vortrag
über zu halten brauche. Zweitens finde ich Java profunde uninteressant,
da sollen sich mal andere so weit mit auseinandersetzen, daß sie
glaubwürdig einen schönen Rant dazu bringen können.
> > Ich will hauptsächlich darauf abheben, daß einem jemand ein an
> > kompilierendes und linkendes Codestück gibt, aber man exorbitant Kontext
> > braucht, um a) das parsen und b) erklären zu können, was dieser Code
> > tut.
> Zeige mir eine Sprache, die dergleichen nicht erfordert.
In C braucht man Größenordnungen weniger Kontext als in C++.
Natürlich kann man sich auch da mit dem Präprozessor gewaltig in den Fuß
schießen.
> > Ich wollte auch auf vtable-Bloat eingehen, und mich über endlose
> > Glue-Wrapper aufregen, aber das ist eher Randprogramm. In der
> > Hauptsache soll es darum gehen, daß es fast unmöglich ist, ein kleines
> > Stück C++-Code außerhalb der gesamten Kompilationseinheit zu betrachten.
> Eh? Das ist letzten Endes bei allen seiteneffektigen Sprachen so.
Ist das so?
strcpy(destbuf,listhead->srcbuf);
Wieviel Kontext brauchst du da, um sagen zu können, was hier passiert?
> > Zuschriften gerne auch per Mail, aber ich vermute mal, die ganze Rotte
> > hier würde sich über eine schöne C++-Schlammschlacht freuen.
> Kannst Du den Vortrag irgendwann ins Netz hängen?
Klar kann ich.
> Inwiefern ist dasein Problem von C++? Bzw. mir erschließt sich gerade nicht,
> inwiefern ein <java>baz = foo.bar(3)</> weniger komplex sein sollte (wenn man
> mal von der leicht abstrahierten Speicherverwaltung absieht.
Java läßt schon ein paar Sachen weg, die sowas verkomplizieren könnten.
Beispielsweise Operator Overloading.
>>>Ich weiß ja nicht, welchen C++-Compiler du so verwendest, aber bei
>>>allen, die ich in den letzten 10 Jahren benutzt habe, war eine sehr
>>>brauchbare Stringklasse dabei.
>>Tja, nur die Frage ist, ob diese Klassen zum Standard gehören.
> Selbstverständlich.
>>Es wird zwar immer gesagt, C und C++ wären äußerst portabel, aber das
>>gilt nur für relativ wenige Programme.
> Interessanterweise kann man damit aber noch sehr viel machen. Einen
> C-Compiler schreiben zum Beispiel. Oder einen MPEG-Decoder. Oder einen
> großen Teil der Unix-Kommandozeilentools (grep, cat, ...). Und die kann
> man dann mit den verschiedensten Compilern übersetzen. Meine Hobby-
> Projekte übersetze ich routinemäßig mit drei verschiedenen Compilern
> (GNU, Turbo C, Borland C++). Die, mit denen ich Geld verdiene, mit vier
> verschiedenen (GNU, MSVC, sowie zwei für Embedded-Plattformen).
Mag ja alles sein, aber schon die heutzutage nun wirklich triviale
Grundanforderung, Applikationen mit GUI zu ermöglichen, macht einem
entweder die Portabilität kaputt oder man braucht wieder irgendwelche
Libraries, die in der Standardplattform einfach nicht drin sind.
In dem Punkt ist Java dem was C++ so bietet nun wirklich Lichtjahrzehnte
voraus.
> GUI hast du nur in Sprachen, die sich auf eine Plattform festlegen.
> Entweder eine native Plattform (MFC -> Win32), oder eine emulierte
> solche (Java).
Solange die "emulierte" solche effektiv auf jeder ernsthaft denkbaren
Zielplattform ohne größere Klimmzüge verfügbar ist, hat man sich damit
von selbigen entkoppelt. Genau das ist der Sinn einer VM.
Es hilft, wenn man Regeln aufstellt und sich daran hält (z.B. "in
Datenstrukturen eingetragene Objekte werden nur zum Zeitpunkt X, Y, und
Z zerstört" und "nur Funktionen A, B, C dürfen eine Referenz auf das als
Parameter übergebene Objekt permanent speichern"). Hilft dir natürlich
beim Audit nicht.
>> bool operator<(const A&, const A&) { return rand() & 1; }
>>dürfte eine std::map<A,int> recht verlässlich abschießen (mit dem
>>Äquivalent davon hab ich allerdings auch schon Solaris' qsort zerlegt).
>
> Ja, so ähnlich. Aber das finde ich "zu einfach", weil es operator
> overloading beinhaltet. Das ist ja schon fast ein Klischee, auf
> operator overloading rumzuhauen.
Statt eines absichtlich bösartigen operator< kannst du auch einen
unabsichtlich bösartigen verwenden. Die Vergleichsfunktion, mit der ich
Solaris' qsort zerlegt hatte, war
int ComparePosition(const void* pp, const void* qq) {
Uns16 p = *(const Pos*)pp, q = *(const Pos*)qq;
int dx = pp->x - qq->x;
if (dx) return dx;
int dy = pp->x - qq->y;
if (dy) return dy;
return p - q;
}
und das ist halt leider keine richtige Sortierreihenfolge. Unter Linux
und Windows tat's dennoch.
>>A propos map: 'if (m[x] == 0)' legt dir selbstverständlich das Element
>>'x' in der map an, falls es noch nicht drin ist.
>
> Natürlich.
>
> Ich finde es ja grandios, daß operator[] bei einem std::vector kein
> range check macht, und man dafür at() nehmen muß. Was geht denn bitte
> in solchen Leuten vor?!
[] muss keinen Range-Check machen, darf aber schon. Ist wohl ein
Zugeständnis an die Leute, die mit damals aktueller Compilertechnologie
dennoch effiziente Programme haben wollen. Damit benimmt sich [] genauso
wie der eingebaute []-Operator.
>>Und meine Tage haben leider auch nur 24 Stunden, sonst wäre mein
>>hübscher kleiner ELF-Linker schon viel weiter.
>
> Wo kann man sich denn den Zwischenstand mal angucken?
<http://phost.de/~stefan/ild/>. Bitte nicht zu sehr verreißen. Hab ich
gerade eben aus dem CVS gezogen und compilierbar gemacht, ansonsten hab
ich da 2003 das letzte mal was ernsthaftes dran getan.
Hintergrund: mein Bastelprojekt brauchte auf 200 MHz / 32 MB knapp 5
Minuten zum Linken. Also beschloss ich, dem durch einen klevereren
Linker abzuhelfen. Der Librarian (ar) ist sogar fertig geworden und war
schön schnell. Das Binary war sogar nur halb so groß wie das damalige
Binary von GNU ar, obwohl es in C++ geschrieben ist. Er ist gut genug,
dass ich ihn täglich einsetze. Der Linker kann ungefähr "Hello world".
Dann kam der neue Rechner mit 2 GHz / 1 GB RAM, und schon war irgendwie
der Leidensdruck weg. Ansonsten hätte ich zahllose Ideen, was man da
noch machen könnte. Die Tatsache, dass ich seit Ende 2003 kein Student
mehr bin, trug aber auch dazu bei, dass ich primär andere Dinge tue.
>>In der Praxis hab ich hier drei Compiler, die bei meinen DSP-Kram Code
>>mit Laufzeitunterschieden von Faktor 10 und mehr auseinander generieren.
>>Und selbst beim schnellsten davon bringt Schleifen aufrollen noch was,
>>weil der nicht von selbst auf die Idee kommt, bei einem 10-tap-FIR das
>>Array mit den 10 Speichergliedern in 10 Registern zu parken.
>
> Ja, das werde ich auch erwähnen. Manche Sachen bringen was. Unrolling
> z.B.
>
> Aber was so gut wie nirgends was bringt ist das Umstellen von
> indexbasiertem Arrayzugriff auf Zeigerarithmetik. Oder manuelle
> Strength Reduction. Umstellen von x/4 auf x>>2. Sowas.
"x/4" zu "x>>2" bringt möglicherweise bei möglicherweise vorzeichen-
behafteten Zahlen (aka int) was. Da das anderes Rundungsverhalten hat,
macht der Compiler das nicht automatisch. Also entweder brav casten,
oder selber shiften.
Ich lese oft (zu oft) den generierten Assemblercode. In der neusten
Version des Compilers hat der Prozessorhersteller das eingesehen, und
packt jetzt wunderbare Boxcomments vor jede Funktion und jede Schleife:
"in dieser Schleife nutzen wir die Register R0-R5 sowie P0-P2, und im
Akkumulator A0 befindet sich die Variable 'sum'. Wir haben 17 parallele
Operationen. Die MAC-Einheit ist dabei zu 95% ausgelastet, der Shifter
zu 10%, DAG0 zu 20% und DAG1 zu 5%". Find ich hübsch :-)
Stefan
Wir machen aber keine Typinferenz a la Haskell ("das Ergebnis ist ein
const char, also rufen wir die const-Methode auf"), sondern die Typen
werden schön von innen nach außen aufgelöst: 's' ist std::string, und
damit ist die am besten passende []-Methode die, die einen 'string*' als
this-Pointer hat, nicht die mit dem 'const string*'.
>>Das Problem im obigen Stueck Code ist dass seine Gueltigkeit davon abhaengt
>>ob auf 's' schreibend zugegriffen werden kann, was in der Tat verwirrend
>>ist.
>
> Mein Verständnis ist bisher, daß immer der const Operator genommen wird,
> solange man darauf nur lesend zugreift.
Nein, es wird immer der nonconst-Operator genommen, sobald du
theoretisch schreiben könntest. Ob du schreiben willst, spielt keine Rolle.
Ja, das saugt, aber nachdem ich die Overload-Resolution mal
implementiert habe, weiß ich, dass die genau so sein muss wie sie ist,
weil all die "offensichtlichen" Verbesserungen mit irgendwas anderem
kollidieren.
Stefan
> if (dx) return dx;
> int dy = pp->x - qq->y;
> if (dy) return dy;
> return p - q;
> }
> und das ist halt leider keine richtige Sortierreihenfolge. Unter Linux
> und Windows tat's dennoch.
Aehm, also da sind diverse Auffaelligkeiten drin:
1. void ptr, siehe oben.
2. Einmal wird 'x' mit 'x' verglichen, einmal 'x' mit 'y'.
3. Es wird nicht immer 0, -1 oder 1 zurueckgegeben.
4. Objekte nach ihrer Adresse zu sortieren (ich vermute nur das das in der
letzten Zeile geschieht) hat ja wohl auch keinen Sinn, insbesondere wenn
man den Unterschied der Adressen einfach nach 'int' castet.
An welchem dieser Syndrome ist Solaris qsort denn gestorben? Und wie war der
Code wirklich?
Uli
A!S
--
Wer tugendhaft lebt und handelt, der legt seinen Adel an den Tag.
-- Giovanni Boccaccio, Das Dekameron
Hrmpf.
In Wirklichkeit waren p und q 'unsigned 16 bit' (steht ja auch noch da),
und es wurden Accessor-Funktionen aufgerufen. Die wollte ich der Kürze
wegen halt rausretuschieren. Hier ist der echte Code (jetzt wirklich
cut&paste):
int ComparePosition(const void* pp, const void* qq)
{
Uns16 p = *(const Uns16*)pp, q = *(const Uns16*)qq;
int dx, dy;
dx = ShipLocationX(p) - ShipLocationX(q);
if (dx)
return dx;
dy = ShipLocationX(p) - ShipLocationY(q);
if (dy)
return dy;
return p - q;
}
> Aehm, also da sind diverse Auffaelligkeiten drin:
> 1. void ptr, siehe oben.
> 2. Einmal wird 'x' mit 'x' verglichen, einmal 'x' mit 'y'.
Genau daran ist qsort gestorben. Weil das ganze dann nicht mehr
symmetrisch ist.
> 3. Es wird nicht immer 0, -1 oder 1 zurueckgegeben.
Das ist egal, zählt ja nur >0 oder <0.
> 4. Objekte nach ihrer Adresse zu sortieren
Sowas als letzter Ausweg sorgt zumindest dafür, dass die Ausgabe nicht
von qsort abhängt :-) (...sondern vom Allokator)
Stefan
Deswegen schreibe ich aber nicht den Arbeitscode in einer Sprache, die
mich an eine Plattform kettet.
> In dem Punkt ist Java dem was C++ so bietet nun wirklich Lichtjahrzehnte
> voraus.
Ein Java-Programm, dass seine Plattform in Form einer multimegabyte-
schweren JVM mitbringt ist jetzt konzeptuell nicht wirklich "Licht-
jahrzehnte voraus" gegenüber einem C++/Pascal/Basic-Programm, das seine
Plattform in Form einer ebensogroßen VM (z.B. VMWare-Player + Win95
drin) mitbringt. FdI 352.
>> Entweder eine native Plattform (MFC -> Win32), oder eine emulierte
>> solche (Java).
>
> Solange die "emulierte" solche effektiv auf jeder ernsthaft denkbaren
> Zielplattform ohne größere Klimmzüge verfügbar ist, hat man sich damit
> von selbigen entkoppelt. Genau das ist der Sinn einer VM.
Sie ist verfügbar auf gängigen PC- und ggf. Server-Plattformen. Ich
mache Embedded, und schon ist Java ganz weit weg. Es gibt wohl irgendwo
eine einfachste JVM für µLinux, aber warum soll ich mir das antun? Zumal
für einen Prozessor, der zwei, drei Größenordnungen weniger häufig
verkauft wird als x86-Kram, auch keiner einen gescheiten JIT entwickeln
wird.
Stefan
Was?
-is
--
seal your e-mail: http://www.gnupg.org/
A°S
--
Es ist besser die Angst als die Hoffnung zu haben.
-- Theodor Fontane
> Dietz Proepper wrote:
>
>
>> Inwiefern ist dasein Problem von C++? Bzw. mir erschließt sich gerade
>> nicht, inwiefern ein <java>baz = foo.bar(3)</> weniger komplex sein
>> sollte (wenn man mal von der leicht abstrahierten Speicherverwaltung
>> absieht.
>
> Java läßt schon ein paar Sachen weg, die sowas verkomplizieren
> könnten. Beispielsweise Operator Overloading.
Das finde ich wiederum total bekloppt. Wenn ich es zulasse Methoden zu
überlagern, sollte das auch mit Operatoren gehen. Die Unterscheidung
zwischen Methode und Operator an sich finde ich konzeptionell schon
leicht merkwürdig.
mfg
Oli
--
Man darf ruhig intelligent sein, man muss sich nur zu helfen wissen.
> Ignatios Souvatzis schrieb:
>> Felix von Leitner wrote:
>>> Wird bestimmt genau so ein Erfolg wie das, was sie da gerade in
>>> London vorgestellt haben.
>>
>> Was?
>>
> Dopingkontrollen bei der Tour de France?
Fahrt durch den Kanaltunnel oder auf der Fähre?
Die wollen den Ärmelkanal ausbaggern?
> Was?
> -is
http://www.rte.ie/news/2007/0704/steorn.html
Jens
--
sage@guug Berlin: http://www.guug.de/lokal/berlin/index.html
> Java läßt schon ein paar Sachen weg, die sowas verkomplizieren könnten.
> Beispielsweise Operator Overloading.
>
Das wiederum wird z.B. von FreePascal und FreeBasic unterstützt. Ich bin
sowieso der Meinung, daß eine Sprache, die nativ kompilierte Binaries
erzeugt, im Zweifelsfall besser ist als eine Interpretersprache oder
irgenwelche Geschichten mit VMs. Solche Ansätze hat es früher übrigens
auch schon gegeben (z.B. UCSD P-System oder EUMEL/ELAN). Warum hat sich
das wohl nicht durchgesetzt?
Gruß,
Oliver
--
Ham Radio Station DL1YOV: http://www.mydarc.de/dl1yov
"it is based on the interaction of magnetic fields"
Oh, ein Dynamo.
"Mr McCarthy revealed that if the technology is validated in scientific
tests, the company plans to licence it over the internet to any company
who wants it for 'a very small fee'."
Die Auslagen für die Fantastilliarden Dollars only in Cash from late
President Grandfather, die mir dauernd angeboten wurden, waren auch "a
very small fee".
Falk
>>Java läßt schon ein paar Sachen weg, die sowas verkomplizieren könnten.
>>Beispielsweise Operator Overloading.
> Das wiederum wird z.B. von FreePascal und FreeBasic unterstützt.
Das wiederum halte ich für einen Rückschritt.
BTW: ein sehr kluger Mann hat mal festgestellt, daß alle ernsthaft
beachtenswerten Versuche, Pascal im Rahmen des prozeduralen Paradigmas
zu verbessern, immer darauf hinaus liefen, irgendetwas wegzulassen.
> Ich bin
> sowieso der Meinung, daß eine Sprache, die nativ kompilierte Binaries
> erzeugt, im Zweifelsfall besser ist als eine Interpretersprache oder
> irgenwelche Geschichten mit VMs.
Das sehe ich nicht so. Der einzige wirkliche Vorteil von nativen
Binaries ist Performance, die aber wiederum ist bereits für den weitaus
überwiegenden Teil des derzeit existierenden Codes in ziemlich weiten
Grenzen unkritisch. Selbst in extrem zeitkritischen Softwarepaketen wie
komplexen Simulationen sind praktisch immer nur einige wenige Routinen
Performancekritisch, beim Rest wäre selbst eine Verlangsamung um den
Faktor 1000 in der Praxis völlig wurst.
Moderne Maschinen verbringen als Client wie als Server bis auf sehr
wenige Ausnahmefälle ihre Rechenzeit weitaus überwiegend mit Warten oder
bei spezielleren Systemen mit einigen wenigen zeitkritischen Routinen.
Ob die Sekretärin hingegen 10^-10 oder 10^-3 Sekunden warten muß, bis
die Eingabemaske der Buchhaltungssoftware angezeigt wird, ist
nachvollziehbar unwichtig. Der wirklich bremsende Flaschenhals ist
beinahe immer I/O, seltener Speicher und nur gaaanz selten die CPU - und
in letzterem Fall ist noch seltener, daß die CPU-Performance sich nicht
mit relativ wenig Geld skalieren ließe.
Ein riesiger Teil des Codes moderner Softwarepakete wird zudem überhaupt
nur sehr selten oder gar nicht im Ausführungspfad landen, weil es sich
um Exception-Behandlung oder selten benötigte Funktionalitäten handelt.
Auch da geht der Deal, mit CPU-Zeit oder Memory für Entwicklerzeit zu
bezahlen, meistens wirtschaftlich ab.
Für all diesen Code hat dei VM enorme Vorteile an allen Fronten - von
der Sicherheit über Portierbarkeit und Wartbarkeit bis zur
Hochverfügbarkeit (VMs lassen sich z.B. in geeigneten Umgebungen
verteilen und automatisch zwischen Clusterknoten migrieren, ohne daß die
darin laufende Anwendung davon überhaupt etwas mitbekäme).
> Solche Ansätze hat es früher übrigens auch schon gegeben (z.B. UCSD P-System
> oder EUMEL/ELAN). Warum hat sich das wohl nicht durchgesetzt?
Weil das Verhältnis zwischen verfügbarer und benötigter Rechenleistung
speziell im Massenmarkt ein ganz anderes war.
Anfang der 80er, als UCSD/p z.B. ein Thema war, verbrachte der User bei
ernsthaften Anwendungen im Massenmarkt regelmäßig die meiste Zeit damit,
auf das System zu warten. Schon einfache Hintergrundprüfungen etwa
während der Texterfassung in einem Editor brachten spürbare
Verzögerungen mit sich, zumal auch Threading und Multitasking eher
selten verfügbar waren.
Eine Software wie MS-Word 2.0 könnte man bereits auf Rechnern, die heute
an der Grenze zur Antiquität stehen, ohne Weiteres in einem System
ähnlich UCSD-Pascal schreiben, ohne daß dabei schlechtere Performance
rauskäme als auf den zu Word 2.0-Zeiten üblichen Rechnern.
Selbst dicke und fette Software-Brocken wie Photoshop, SAP R/3 oder
OpenOffice wären durchaus dergestalt denkbar, daß 95% des Codes auf
einer VM-Plattform laufen und nur ein paar zentrale Routinen, die für
den Benutzer wirklich Performancekritisch sind, nativ implementiert werden.
Für sowas gibts übrigens durchaus prominente Beispiele. Bei CAD-Software
z.B. trifft man meistens einen relativ kleinen, hochoptimierten
Rechenkern an und einen Interpreter mit einer Art Makro-Sprache, in der
dann die meisten High-Level-Funktionen implementiert werden. Erhebliche
Teile des Anwenderseitig sichtbaren Funktionsumfang von GIMP sind über
Script-Fu realisiert worden - auch das ist im Grunde eine Art VM. Die
Basic-Compiler von Microsoft aus den 90ern sind den Weg über einen
p-Code gegangen, der dann von einer dazugelinkten Runtime (die im Grunde
ebenfalls nichts anderes ist als eine primitive VM) interpretiert wurde.
> Wenn ich es zulasse Methoden zu
> überlagern, sollte das auch mit Operatoren gehen. Die Unterscheidung
> zwischen Methode und Operator an sich finde ich konzeptionell schon
> leicht merkwürdig.
Du willst FORTH.
Servus,
Konni
--
Gruselige Geschichten von Edgar Allan Poe:
http://www.roterochs.de/veranstaltungen/literarisches-dinner.html
>>> Du willst also ein Faltblatt "Wie schreibe ich sauberes C++" verkaufen?
>>
>> Das könnte man dann als Unterlage für die Emacs-Referenztasse (ihr wisst
>> schon, die, die man bei Regen als Unterstand benutzen kann) verwenden.
>>
> s/tasse/mousepad/
Eine Unterlage für ein Mousepad? Also ein rutschiges Stück Papier, damit das
Mosepad zusammen mit der Maus verschoben werden kann? Sowas Tolles wollte ich
ja noch nie!
--
"Cluster bombing from B-52s is very, very accurate. The bombs are
guaranteed to always hit the ground."
-U.S.A.F. Ammo Troop
Friß, Spammer: q6...@f.7eggert.dyndns.org kvpt...@ug.7eggert.dyndns.org
> Dietz Proepper wrote:
>
>
>> Inwiefern ist dasein Problem von C++? Bzw. mir erschließt sich gerade
>> nicht, inwiefern ein <java>baz = foo.bar(3)</> weniger komplex sein
>> sollte (wenn man mal von der leicht abstrahierten Speicherverwaltung
>> absieht.
>
> Java läßt schon ein paar Sachen weg, die sowas verkomplizieren
> könnten. Beispielsweise Operator Overloading.
Generell ja richtig, hat mit dem Codeschnipsel allerdings nichts zu tun.
--
MfG usw.
Werner Mahr
> Eher »kleiner _oder_ größer« analog zu >=. Aber wenn man ! (not) und
> == (gleich) kennt, erschließt sich einem die Bedeutung von != von
> selbst.
Dann müsste es ja eigentlich !== heißen. != wäre dann wohl ein Anweisung
die sagt: Bitte nicht zuweisen, falls doch dann Fehler.
> Die wollen den Ärmelkanal ausbaggern?
Ja, da soll jetzt ein Baggersee draus werden.
> Am Sat, 07 Jul 2007 18:59:34 +0200 schrieb Erhard Schwenk:
>
>> Java läßt schon ein paar Sachen weg, die sowas verkomplizieren
>> könnten. Beispielsweise Operator Overloading.
>>
> Das wiederum wird z.B. von FreePascal und FreeBasic unterstützt. Ich
> bin sowieso der Meinung, daß eine Sprache, die nativ kompilierte
> Binaries erzeugt, im Zweifelsfall besser ist als eine
> Interpretersprache oder irgenwelche Geschichten mit VMs.
Die Bewertung ließe sich ja nur anhand konkreter Anforderungen
vornehmen.
He, weils langsam und bloatig ist! Java dagegen, äh, ...
Vergiss es.
Viele Grüsse,
VB.
--
"Es muss darauf geachtet werden, dass das Grundgesetz nicht mit Methoden
geschützt wird, die seinem Ziel und seinem Geist zuwider sind."
Gustav Heinemann, "Freimütige Kritik und demokratischer Rechtsstaat"
Die Grundeinstellung, die 2GHz-Maschinen erforderlich macht, um Windows
zu starten.
So what? Die 2GHz-Maschine ist heutzutage ohnehin auf dem Schreibtisch
vorhanden, und sie langweilt sich mehr als 90% der CPU-Zeit. Eine
langsamere Maschine ist kaum noch zu bekommen, schon gar nicht
nennenswert billiger.
Im Embedded-Bereich mag es noch etwas anders aussehen, aber auch da sind
wir längst bei 500 MHz und 2GB RAM in der Größe eines Modems (z.B.
Soekris 5501).
Sprich: die Grenzkosten der Rechenleistung sind in weiten Bereichen 0
oder gar negativ. Die Grenzkosten von Entwicklerzeit sind immer noch
positiv, ergo wird an der Front eben so viel wie möglich gespart, auch
wenn das Rechenleistung kostet. An sich ein einfacher, logischer und
völlig nachvollziehbarer Vorgang.
Beim RAM sind die Verhältnisse noch nicht ganz so extrem, aber auch da
interessiert einfach keine Sau mehr, ob der Schreibtisch-PC 500 MB RAM
braucht. Es gibt ohnehin kaum mehr welche mit weniger zu kaufen.
Ich finde ihn auch logisch und nachvollziehbar. Nur dass er falsch ist.
Vom Umweltstandpunkt noch ganz abgesehen (Computer könnten nur noch
einen Bruchteil der Leistung erfordern, die sie heute fordern), ist es
schlicht so, dass wenn ich Anwender beobachte, dass sie immer noch
ständig auf ihren Computer warten.
Das Argument, dass das nicht so sei, widerlegt jeder SAP-Client und
jedes Java-Programm, das ich jemals gesehen habe auf einem Desktop-
Rechner.
Lion's book, sag ich da nur. Und Stevens/Wright, TCP/IP Illustrated Vol 2.
-is
>Vom Umweltstandpunkt noch ganz abgesehen (Computer könnten nur noch
>einen Bruchteil der Leistung erfordern, die sie heute fordern), ist es
>schlicht so, dass wenn ich Anwender beobachte, dass sie immer noch
>ständig auf ihren Computer warten.
Die Geschwindigkeit von Desktop-Programmen hat keine signifikant
technologische Komponente. Sie richtet sich nach dem Schmerzempfinden
der Anwender, und ein bisschen lahm tut nicht genuegend weh.
--
--
Michael van Elst
Internet: mle...@serpens.de
"A potential Snark may lurk in every tree."
>Sprich: die Grenzkosten der Rechenleistung sind in weiten Bereichen 0
>oder gar negativ.
Erzaehl das deiner Stromrechnung.
Mir fiel bei der Beschreibung eher die Szene aus Accelerando ein, wo sie
große Spulen auf einem Meteoriten parken, die dann durch das Magnetfeld
eines Planeten ziehen. Kann man sicher auch in klein nachbauen und
bringt dann ein paar Nanovolt.
Stefan
Natürlich. Beim Einfügen in eine Liste ist Faktor 1000 völlig Wurst.
Beim Erstellen eines Dialogfeldes ist Faktor 1000 völlig Wurst. Beim
Zusammenstellen eines Netzwerkpakets ist Faktor 1000 völlig Wurst. Nur,
tut man das alles zusammen, ist man auf einmal bei Faktor 1000000000.
> Moderne Maschinen verbringen als Client wie als Server bis auf sehr
> wenige Ausnahmefälle ihre Rechenzeit weitaus überwiegend mit Warten oder
> bei spezielleren Systemen mit einigen wenigen zeitkritischen Routinen.
Komisch. Ich verbringe viel zu viel Zeit mit dem Warten auf den Rechner.
Warum braucht der verf***te Acrobat Reader geschlagene 10 Sekunden, um
das blöde Suchfenster einzublenden? Warum braucht der eine halbe Minute
zum Starten?
Warum braucht Windows zwei Minuten zum Reinpagen des Thunderbird, wenn
ich den 10 Minuten nicht benutzt habe, wo doch mein Working-Set
wesentlich kleiner als der RAM ist?
> Ob die Sekretärin hingegen 10^-10 oder 10^-3 Sekunden warten muß, bis
> die Eingabemaske der Buchhaltungssoftware angezeigt wird, ist
> nachvollziehbar unwichtig.
Real unterhalten wir uns aber vielleicht über 10^-4 bis 10^2, und das
ist merkbar. Insbesondere, wenn du 10^2 Instanzen davon auf nem
Terminalserver laufen hast.
> Ein riesiger Teil des Codes moderner Softwarepakete wird zudem überhaupt
> nur sehr selten oder gar nicht im Ausführungspfad landen, weil es sich
> um Exception-Behandlung oder selten benötigte Funktionalitäten handelt.
> Auch da geht der Deal, mit CPU-Zeit oder Memory für Entwicklerzeit zu
> bezahlen, meistens wirtschaftlich ab.
Ich habe nichts gegen den Deal (hey, sonst würde ich Assembler
schreiben!), bin aber gegen sinnlose Performancevernichtung.
Stefan