PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Geschwindigkeitsvergleich zwischen C++/Qt und C#


Djon
2007-10-05, 11:14:26
Hallo!

In unseren Team gibt es zwei Parteien, die einen schwören auf C++/Qt, die anderen auf C#. Für C++/Qt spricht die Geschwindigkeit, Portabilität und direkte Speicherverwaltung. Für C# dagegen kürzere Entwicklungszeit, Komfortabilität bei der Entwicklung (keine Speicherverwaltung) usw.
Gestern waren wir soweit, dass wir die ganzen Vorurteile aufräumen wollten und wir starteten einen Test. Dieser Test bestand darin, eine Klasse zu erstellen. Diese Klasse hat eine Listenstruktur, in die man Strings ablegen kann. Zusätzlich wird noch eine Methode zur Verfügung gestellt, die die Summe über die einzelnen Strings bildet und diese zurück gibt. In der Main-Routine werden 100000 Objekte von dieser Klasse erstellt, wobei jedes Objekt 100 Strings (1..100) in seine privaten Listenstruktur hat. Anschließend geht man durch die Liste mit Objekten durch und bildet die Gesamtsumme über alle Objekte.
Ich muss sagen, dass Ergebnis war sehr überraschend, C# war um ca. 100% schneller als C++/Qt. Ich konnte meinen Augen nicht glauben :confused:

Das schlechte Ergebnis wurde auf das Verwenden von QStrings geschoben. Im zweiten Test wurden die Strings durch Integer-Variablen ersetzt und siehe da, C# wurde plötzlich ca. 600% - 700% schneller als C++/Qt :eek:

Woran kann das liegen? Wieso ist C# so schnell, auch bei nativen Datentypen?

Mfg Djon

Ganon
2007-10-05, 11:21:00
Ohne den Code und die Daten der Testumgebung an sich, kann man das wohl schlecht beurteilen ;)

Gast
2007-10-05, 11:38:45
Vielleicht weil Speicherallokation mit Garbage Collection schneller geht?

Chris Lux
2007-10-05, 11:41:02
Debug Modus? Visual Studio 2005 verwendet fuer die C++ Tests mit stl listen und strings und _SECURE_SCL=0 vergessen?

malte.c
2007-10-05, 12:42:21
Wenn Du willst, kannst Du auch einen Test schreiben, der das Gegenteil beweist. Die Geschwindigkeit von Programmiersprachen kann man allgemein nicht bewerten, es hängt immer auch maßgeblich vom Compiler und noch wesentlicher vom zu lösenden Problem ab und der Implementierung ab.

Ist Eure zu entwickelnde Software denn überhaupt geschwindigkeitskritisch? Und wenn ja, ist die Kernaufgabe dieser Software das, was Ihr in diesem Test geprüft habt?

Trap
2007-10-05, 13:09:57
Woran kann das liegen? Wieso ist C# so schnell, auch bei nativen Datentypen?
Weil du genau das getestet hast was mit Sicherheit am besten optimiert ist in C# und in C++ weit weniger.

Das ist ungefähr so sinnvoll wie ein Test Perl RE gegen QT Regexp, da würde auch die "langsamere Sprache" gewinnen.

rotalever
2007-10-05, 15:36:43
Wenn man Programmiersprachen vergleichen will sollte man folgenderweise vorgehen: Gegeben sind Eingabedaten, ein fest vorgeschriebener Algorithmus und Ausgabedaten zur Verifizierung. Für jede Programmiersprache sucht man sich nun einen Spezialisten mit viel Erfahrung und lässt ihn den Algorithmus in seiner Sprache implementieren. Dann vergleicht man die Geschwindigkeiten. Alles andere bringt gar nichts.

Das sind dann wie die Java-C++ Benchmarks wo herauskommt, dass Java schneller ist als C++. Eine andere Seite schreibt dann: "Hier und hier und hier kann man das C++ noch optimieren". Die Folge ist, dass das C++ auf einmal deutlich schneller ist.

Djon
2007-10-05, 16:02:19
Hallo!

Das C++/Qt-Programm haben wir natürlich schon als release kompiliert.
Wir planen demnächst ein Analyse-Tool zu schreiben, welches sich mit großen Datenmengen beschäftigen wird. Bei diesem Test bin ich davon ausgegangen, dass eine direkte Speicherverwaltung, nämlich die sofortige Freigabe vom nicht mehr verwendeten Speicherplatz, deutliche Speichervorteile mit sich bringen würde. Doch auch in diesem Bereich war C++/Qt nicht auf der Höhe gewesen.
Das C++/Qt-Programm wurde mit VC++ 6.0 entwickelt und wir vermuten, dass es doch an dem etwas älteren Compiler liegt. Das C#-Programm wurde mit Hilfe von Visual Studio .Net 2005 entwickelt.

Mfg Djon

Trap
2007-10-05, 16:08:01
Einigermaßen brauchbar als Performancevergleich ist http://shootout.alioth.debian.org/gp4sandbox/benchmark.php?test=all&lang=all

.NET ist mit Sicherheit deutlich schneller als Mono.
Das C++/Qt-Programm wurde mit VC++ 6.0 entwickelt und wir vermuten, dass es doch an dem etwas älteren Compiler liegt.
Du benutzt einen Compiler der älter als der C++-Standard ist um irgendwas über C++ herauszufinden? :eek:

Trap
2007-10-05, 16:26:53
Bei diesem Test bin ich davon ausgegangen, dass eine direkte Speicherverwaltung, nämlich die sofortige Freigabe vom nicht mehr verwendeten Speicherplatz, deutliche Speichervorteile mit sich bringen würde.
Du testest im Grunde nur den Verwaltungsoverhead der Allokation und Deallokation. Da ist .NET besser, grade wenn man so einfache Objektstrukturen und Lebenszeiten hat, da muss der GC fast nichts machen.

Djon
2007-10-05, 16:57:22
Hallo!

Wir werden den Test am Montag nochmal durchführen, diesmal unter verwendung des aktuellen gcc-Compilers.

@Trap
Danke für den Link

Mfg Djon

Trap
2007-10-05, 17:16:25
Wir werden den Test am Montag nochmal durchführen, diesmal unter verwendung des aktuellen gcc-Compilers.
Viel anders wird das Ergebnis sicher nicht ausfallen. new/delete sind die Sachen die in deinem Testfall am meisten Zeit brauchen. Dafür wird der GCC ziemlich sicher den gleichen Algorithmus benutzen und deshalb auch nicht deutlich andere Performance zeigen.

Manuelle Speicherverwaltung ist nicht deshalb besser weil new/delete schneller ist (ganz im Gegenteil, new/delete ist ein Schwachpunkt im Vergleich zu GC-Systemen).

Expandable@work
2007-10-05, 17:23:40
Wobei ich noch anmerken möchte, dass Qt-Windows-Apps mir rein subjektiv meistens träger als WinForms-Apps vorkommen. Kann das jemand bestätigen?

SgtTynis
2007-10-05, 17:25:51
Man darf bei laufzeitkompilierten Plattformen wie .NET das Hotspot-Feature nicht vernachlässigen; dagegen steht natürlich die besserer "statische" Optimierung konventionellen Sprachen, aber das ist auch nicht immer der Stein der Weisen. CPU spezifische Optimierungen dürften der .NET Plattform auch einiges an Performance bescheren.

Trap
2007-10-05, 17:29:35
CPU spezifische Optimierungen dürften der .NET Plattform auch einiges an Performance bescheren.
Gibt es die überhaupt? Hast du einen Link wo man das nachlesen kann?

maximAL
2007-10-05, 18:02:03
CPU spezifische Optimierungen dürften der .NET Plattform auch einiges an Performance bescheren.
die bringen schon bei c++ compilern weniger als man hoffen könnte...

Kabelsalat
2007-10-05, 18:07:37
@SgtTynis: Auch bei .Net gibt es in gewissem Rahmen statische Optimierung. Gleichbedeutender C#, VB.Net und C++ / CLI Code hat nicht zwangsläufig identischen IL-Code zur Folge. Auf ebene des Sprachen-Compilers finden nämlich durchaus unterschiedliche "Optimierungen" statt.

HellHorse
2007-10-05, 22:03:37
Für C++/Qt spricht ... direkte Speicherverwaltung.
Ein Grund dafür?!? Direkte Speicherverwaltung ist langsam, fehleranfällig und mühsam. Mittlerweile sagt doch sogar Stroustrup man solle einen "GC" verwenden.
Gestern waren wir soweit, dass wir die ganzen Vorurteile aufräumen wollten und wir starteten einen Test. Dieser Test bestand darin, eine Klasse zu erstellen. Diese Klasse hat eine Listenstruktur, in die man Strings ablegen kann. Zusätzlich wird noch eine Methode zur Verfügung gestellt, die die Summe über die einzelnen Strings bildet und diese zurück gibt. In der Main-Routine werden 100000 Objekte von dieser Klasse erstellt, wobei jedes Objekt 100 Strings (1..100) in seine privaten Listenstruktur hat. Anschließend geht man durch die Liste mit Objekten durch und bildet die Gesamtsumme über alle Objekte.
Super Test, echt jetzt. Kindergarten oder was?

Gast
2007-10-06, 00:34:31
Wenn man Programmiersprachen vergleichen will sollte man folgenderweise vorgehen: Gegeben sind Eingabedaten, ein fest vorgeschriebener Algorithmus und Ausgabedaten zur Verifizierung. Für jede Programmiersprache sucht man sich nun einen Spezialisten mit viel Erfahrung und lässt ihn den Algorithmus in seiner Sprache implementieren. Dann vergleicht man die Geschwindigkeiten. Alles andere bringt gar nichts.

Das sind dann wie die Java-C++ Benchmarks wo herauskommt, dass Java schneller ist als C++. Eine andere Seite schreibt dann: "Hier und hier und hier kann man das C++ noch optimieren". Die Folge ist, dass das C++ auf einmal deutlich schneller ist.


Eben, genau so ist es.


Idealerweise sollte man daher bei solchen Geschwindigkeitstests auch die Wartbarkeit und die Übersichtlichkeit des Codes mitbewerten.

Kein Mensch programmiert heutzutage in der kommerziellen Softwarewelt noch
Programme die zwar hochoptimiert sind, aber Codetechnisch absolut scheiße und unübersichtlich aussehen.


Daher sollte man den Code auch von der Wartbarkeit her vergleichen.

Also wartbarer C++ Code gegen wartbarer C# Code und das wars dann.

rotalever
2007-10-06, 11:16:43
Kein Mensch programmiert heutzutage in der kommerziellen Softwarewelt noch
Programme die zwar hochoptimiert sind, aber Codetechnisch absolut scheiße und unübersichtlich aussehen.
Da wär ich mir mal nicht so sicher :rolleyes:

Djon
2007-10-06, 11:35:13
Super Test, echt jetzt. Kindergarten oder was?

Was besseres und aussagekräftiges ist uns in diesen Moment nicht eingefallen :biggrin:

Mfg Djon

Gast
2007-10-06, 12:04:02
Da wär ich mir mal nicht so sicher :rolleyes:

Die Entwicklungskosten steigen immer mehr, die Programme mächtiger und somit Codetechnisch fetter und die Rechner werden immer schneller,
daher gewinnt Wartbarer Code zunehmend an Bedeutung.


Man geht ja inzwischen schon über Großprojekte in Programmiersprachen mit Garbage Collector zu implementieren, etwas, was man vorher nie getan hätte um nicht die Kontrolle über das Speichermanagement zu verlieren.

rotalever
2007-10-06, 12:28:14
Die Entwicklungskosten steigen immer mehr, die Programme mächtiger und somit Codetechnisch fetter und die Rechner werden immer schneller,
daher gewinnt Wartbarer Code zunehmend an Bedeutung.


Man geht ja inzwischen schon über Großprojekte in Programmiersprachen mit Garbage Collector zu implementieren, etwas, was man vorher nie getan hätte um nicht die Kontrolle über das Speichermanagement zu verlieren.
Meinst du nicht, dass man möglicherweise in großen Projekten auch schon mit C++ Garbage Collectoren teilweise eingesetzt hat? Wäre nur so eine Vermutung von mir. Ansonsten hast du natürlich recht, sinnvoll ist es immer wartbaren Code zu produzieren, solange er noch erträglich schnell ist. Die Sache ist nur, dass faktisch oftmals sehr alter Code jahrelang mitgeschleppt wird und es eben dann nicht übersichtlich ist. Es gibt mit 100% Firmen die das so handhaben und auch etwas verdienen ;)

An den TS: Darf man fragen, was das für eine Projekt ist, an dem ihr mit eurem Team arbeitet.

HellHorse
2007-10-08, 21:01:17
Was besseres und aussagekräftiges ist uns in diesen Moment nicht eingefallen :biggrin:
Als erstes würde ich mir mal Gedanken darüber machen was Ihr überhaupt messen wollt. "der Speed" ist etwa so klar wie ein durchschnittliches Requirement eines Kunden. Ich würde folgendes vorschlagen, sucht ein Problem, das in eurer Firma mit C++ oder C# gelöst werden würde. Stutzt es soweit zusammen, dass man es in einem Nachmittag implementieren kann und vergleicht die Lösungen.

ScottManDeath
2007-10-08, 22:37:15
Ich war mit meinem Raytracer in C# ca 4 bis 10 mal langsamer als diejenigen die C++ verwendet haben. Allerdings habe ich grossen Wert auf ein flexibles Design gelegt und koennte wohl mit einem schlankerem Design Performance erhoehen.

Djon
2007-10-09, 10:10:58
Hallo!

Zur Zeit entwicklen wir im Rahmen unsere Gruppendiplomarbeit eine Stellwerkssimulation für ein Bahnunternehmen. Später wollten wir im Rahmen eines Nebenjobs ein Umfragenanalysetool entwickeln. Und da kam der Streitpunkt auf, welche Programmiersprache für die Entwicklung geeignete wäre. Geeignet heißt für uns: Entwicklungszeit + Performance + Lizenzgebühren. Und so wie ich es jetzt überblicke, ist C++/Qt da wohl sehr ungeeignet :redface:

Mfg Djon

Gast
2007-10-09, 11:10:14
Und da kam der Streitpunkt auf, welche Programmiersprache für die Entwicklung geeignete wäre. Geeignet heißt für uns: Entwicklungszeit + Performance + Lizenzgebühren. Und so wie ich es jetzt überblicke, ist C++/Qt da wohl sehr ungeeignet :redface:

Mfg Djon

Ich empfehle D mit dem GTK Binding für D.

Gute Entwicklungszeit.
Gute Performance.
Keine Lizenzgebühren.

Djon
2007-10-09, 13:09:26
Hallo!

Wie sieht es bei D mit der Entwicklung kommerzieller Anwendungen aus?

Mfg Djon

rotalever
2007-10-09, 13:47:12
Kein GTK. GTK ist nicht so gut auf Windows. D kennen nur sehr wenige, es ist auch immer Vorteil wenn man keine ganz so exotische Sprache nimmt.

Aber Eure Projekte, besonders das letztere sehen nicht danach aus, als käme es da auf 10-30% (ungefähre Angabe zum Verhalten von C++ und C#) Leistungsunterschied an.

Djon
2007-10-09, 13:57:29
Hallo!

Sicherlich kommt es da nicht auf die letzten paar Prozent an, aber es wäre doch auf jeden Fall schönen eine "stille" Performancereserve zu haben. :rolleyes:

Wie sieht es mit Mono C# aus? Ist Mono für kommerzielle Anwendungen kostenfrei?

Mfg Djon

Gast
2007-10-09, 14:45:17
Selbstverständlich.

rotalever
2007-10-09, 15:31:33
Sicherlich kommt es da nicht auf die letzten paar Prozent an, aber es wäre doch auf jeden Fall schönen eine "stille" Performancereserve zu haben. :rolleyes:
Ja wenn ihr halt Perfomance wollt dann nehmt doch das C++. Das Problem ist irgendwie nicht verständlich..

micki
2007-10-09, 15:36:46
Ein Grund dafür?!? Direkte Speicherverwaltung ist langsam, fehleranfällig und mühsam.deiner kristalkugel sollte die marketingmodifikation entfernt bekommen.

Mittlerweile sagt doch sogar Stroustrup man solle einen "GC" verwenden.
und ich dachte er hat gesagt, dass ein GC fuer bestimmte anwendungsbereiche/leute legitim ist.

@Djon
Dem niveau eures test nach und der ahnungslosigkeit wo performance bei c++ drauf geht, ist vermutlich c# die richtige wahl fuer euch. damit werdet ihr zwar kein rennen (gegen jemanden der ahnung hat wie man optimiert) gewinnen , dafuer (wie deine benchmarks zeigen), kompensiert C#/.Net euer ..emm.. "unwissen".

micki
2007-10-09, 15:38:04
Ich war mit meinem Raytracer in C# ca 4 bis 10 mal langsamer als diejenigen die C++ verwendet haben. Allerdings habe ich grossen Wert auf ein flexibles Design gelegt und koennte wohl mit einem schlankerem Design Performance erhoehen.
fexibles design und performance ist kein wiederspruch ;)

Gast
2007-10-09, 15:43:51
deiner kristalkugel sollte die marketingmodifikation entfernt bekommen
Wieso? Er hat doch Recht.

micki@work
2007-10-09, 17:08:36
Wieso? Er hat doch Recht.jetzt hast du mich ueberzeugt, lol.

Gast
2007-10-09, 21:18:02
jetzt hast du mich ueberzeugt, lol.

Bin zwar ein anderer Gast, aber das ist im Allg. bekannt, dass dynam. Speicher i.d.R. fast genau so schnell wie vom Stack allokiert werden kann, weil die VM die Verwaltung im Hintergrund übernimmt. Wenn du ein neues Objekt auf dem Heap anlegst, hat die VM schon einen Zeiger auf genügend freien Speicher. Und falls das mal nicht so ist (also Zeiger + Datenstrukturgröße > Heap/Generation) wird die Garbage Collection gestartet.

micki
2007-10-09, 23:49:59
Bin zwar ein anderer Gast, aber das ist im Allg. bekannt, dass dynam. Speicher i.d.R. fast genau so schnell wie vom Stack allokiert werden kann, weil die VM die Verwaltung im Hintergrund übernimmt. Wenn du ein neues Objekt auf dem Heap anlegst, hat die VM schon einen Zeiger auf genügend freien Speicher. Und falls das mal nicht so ist (also Zeiger + Datenstrukturgröße > Heap/Generation) wird die Garbage Collection gestartet.
das ist eben die dumme marketing argumentation die alle die nicht drueber nachdenken davon ueberzeugt dass es viel schneller ist. um es mal auf ein anderes model zu bilden.

c++ wirft kiesel fuer kiesel ueber die mauer, das ist natuerlich anstrengend. eine VM ist da viel 'leichter', da wirfst du die steinchen in eine kleine tuete... und so ganz im nebensatz als ob es umsonst waere kommt dann der hacken an der milchmaedchenrechnung... und wenn die tuete voll ist, wirft der GC die ganze tuete auf einmal ueber die mauer.

und alle leichtgaelubigen sagen erstmal "ja, wow, das ist ja viel besser, es ist total einfach die steinchen in die tuete zu legen, viel viel leichter als sie ueber die mauer zu werfen, das ist die zukunft." und dann geht man kopfnickend nachhause und fragt sich garnicht wieso es ploetzlich so ein wunder (http://www.youtube.com/watch?v=h6vSxR6UKFM) geben kann ohne das es jeder altgediente informatiker foermlich anbetet.

jeder der ein bisschen grundlagen in physic kennt, der weiss, dass die arbeit trotzdem verrichtet werden muss, ob stueck fuer stueck oder erstmal aufgestaut und dann am stueck.

jeder der ein wenig weiter denkt, der weiss dann auch, dass die reorganisation der VM speicherverwaltung sehr teuer ist, bei kleinen benchmarks garnicht ins gewicht faellt weil eh am anfang meist viel mehr im vorrausallokiert wird vom OS durch die VM-speicherverwaltung.(und es gibt viele algorithmen, manche VMs teilen den speicher in zwei gleich grosse bereiche und wenn sie nicht mehr neu allokieren koennen weil sie am 'ende vom stack' angelangt sind, kopieren sie die bereiche komplett in den anderen block, natuerlich viel ausgekluegelter als ich es hier banal darstelle. andere VMs haben einen stack der zusammengefaltet wird wenn sie volllaufen, was ebenfalls sehr teuer ist etc.)

und wenn sich nun nicht nur jemand findet, der nicht nurweiter denkt, sondern eventuell ein experte ist, der wird feststellen, dass er nicht stumpf die steinchen ueber die mauer werfen muss, denn eventuell kann man sie gleich wiederverwenden oder es sind spezielle steinchen, die sehr wertvoll sind... etwas was eine VM nicht feststellen kann. (falls es jemand nicht weiss, damit spiel ich auf die optimierte speicherverwaltung an, die mittels c++ moeglich ist... manche handyspiele mit java machen sowas aus not aber auch bis zum gewissen grad).

deswegen lohnt es sich nachzudenken, statt der allgemeinen milchmaenchenrechnung zu glauben.
und stellt mich nicht als c++ fanboy dar;), ich programmiere auch so einiges in java und nutze gerne lua, nur weiss ich dass die sprachen andere vorzuege haben und lache ueber jeden marketing-BS der sagt, dass eine VM bzw GC schneller ist als native speicherverwaltung, oder dass man mit java/c# viel geilere graphiken programmieren kann weil es ne schon von haus aus ne graphic-api enthaellt.
Da sollte man sich einfach nicht verarschen lassen. denn die firmen die sowas anpreisen, werden sicherlich ihr produkt nicht schlecht dastehen lassen.

Gast
2007-10-10, 08:23:34
jeder der ein bisschen grundlagen in physic kennt, der weiss, dass die arbeit trotzdem verrichtet werden muss, ob stueck fuer stueck oder erstmal aufgestaut und dann am stueck.


Und jeder, der sich mit der Materie damit etwas auskennt, der weiß, dass die VM deswegen pro Prozess Hintergrundprozesse hat. D.h. die Verwaltungsaufgaben des Speichermanagements werden also nicht erst beim Anfordern ausgeführt, sondern ist da schon längst fertig. Und mit deinem "am Stück" liegst du auch daneben, da die VM schon so schlau ist und in Generationen verwaltet.

Gast
2007-10-10, 08:34:37
^^ Hintergrundthreads mein ich natürlich

Gast
2007-10-10, 10:18:23
^^ Hintergrundthreads mein ich natürlich
Und die verbrauchen keine Prozesszeit?

Nasenbaer
2007-10-10, 11:36:13
Ich versteh die Diskussion ohnehin nicht. Ich hatte mal A* in C++ implementiert und dabei schön STL usw. genutzt. Dann hat mir jemand A* als Java-App gegeben und die war um Längen schneller.
Aber daraus gleich zu schließen, dass Java besser als C++ in Sachen Performance ist, ist völliger Käse. Weil ein Traktor schwere Lasten ziehen kann hängt er also auch nen Ferrari hab? Cool! ;D

Wenn man nicht ausreichend Erfahrung hat um die Geschwindigkeitsverluste im Programm zu finden sollte man einfach seine Lieblingssprache nutzen und nen Profiler um Schwachstellen im Code zu finden.


@micki
Dein Vergleich hingt übrigens ein wenig. Es kann durchaus einfacher Sein eine Tüte Steine zu schmeißen als jeden Stein einzeln. Wenn ich mich für jeden Stein einzeln bücken muss um ihn aufzuheben und das genausoviel kostet wie die ganze Tüte zu heben, dann kann die Tütevariante performanter sein. Geht mir dabei um den Overhead der bei einen Aufruf in der Routine und ihrem aufruf steckt. Dieser kann sich bei mehrfachen Aufruf womöglich summieren und letztendlich ins Gewicht fallen.

Trap
2007-10-10, 12:10:45
das ist eben die dumme marketing argumentation die alle die nicht drueber nachdenken davon ueberzeugt dass es viel schneller ist.
Der Performancevergleich zwischen GC und manueller Speicherverwaltung ist nur sinnvoll wenn man eine oder besser mehrere echte Anwendung hat und sagt wieviel mehr Speicher der GC benutzen darf. Bei nahezu unendlich viel Speicher ist der GC immer schneller, bei 0% Mehrverbrauch immer die manuelle Speicherverwaltung.

Gute GCs sind im allgemeinen bei etwa 30% des dynamisch genutzten Speichers als Mehrverbrauch genauso schnell wie manuelle Speicherverwaltung.

micki@work
2007-10-10, 12:22:09
Ich versteh die Diskussion ohnehin nicht. Ich hatte mal A* in C++ implementiert und dabei schön STL usw. genutzt. Dann hat mir jemand A* als Java-App gegeben und die war um Längen schneller.
Aber daraus gleich zu schließen, dass Java besser als C++ in Sachen Performance ist, ist völliger Käse. Weil ein Traktor schwere Lasten ziehen kann hängt er also auch nen Ferrari hab? Cool! ;DKlar, hat ja weit mehr PS. Lamborgini hat ja auch urspruenglich traktoren gebaut *Hehe*

Wenn man nicht ausreichend Erfahrung hat um die Geschwindigkeitsverluste im Programm zu finden sollte man einfach seine Lieblingssprache nutzen und nen Profiler um Schwachstellen im Code zu finden. man sollte auch nicht dauernt komplexe wegen geschwindigkeit haben. Ich weiss auch dass man in Assembler schnellere anwendungen als in c++ coden kann und behaupte nicht blind irgendwelchen duenpfiff (z.b. mit templates ist man mit c++ trotzdem schneller), sondern waehle c++ aus ganz anderen gruenden. und die meisten studenten wuerden wahrscheinlich auch rausfinden dass c++ 100mal schneller als assembler ist wenn sie es benchen... das sagt in dem fall nur aus, wie gut der programmierer ist und gleichzeitig dass er dann nicht assembler nehmen sollte *hehe*.


@micki
Dein Vergleich hingt übrigens ein wenig. Es kann durchaus einfacher Sein eine Tüte Steine zu schmeißen als jeden Stein einzeln. Wenn ich mich für jeden Stein einzeln bücken muss um ihn aufzuheben und das genausoviel kostet wie die ganze Tüte zu heben, dann kann die Tütevariante performanter sein. Geht mir dabei um den Overhead der bei einen Aufruf in der Routine und ihrem aufruf steckt. Dieser kann sich bei mehrfachen Aufruf womöglich summieren und letztendlich ins Gewicht fallen.
klar, du kannst dir auch nen bruch heben wenn du die ganze tuete am stueck versuchst zu heben. mein beispiel sollte ja auch keine 1:1 mapping zwischen c++ und VM-sprachen darstellen, sondern die milchmaenchen rechnung zeigen. denn die arbeit mit der speicherverwaltung muss trotzdem gemacht werden, egal ob es als extra thread, oder on-demand passiert. there is no lunch for free.

micki@work
2007-10-10, 12:39:21
Der Performancevergleich zwischen GC und manueller Speicherverwaltung ist nur sinnvoll wenn man eine oder besser mehrere echte Anwendung hat und sagt wieviel mehr Speicher der GC benutzen darf. Bei nahezu unendlich viel Speicher ist der GC immer schneller, bei 0% Mehrverbrauch immer die manuelle Speicherverwaltung. wenn beiden gleich viel speicher zur verfuegung steht (also z.b. unendlich) hast du gleiche geschwindigkeit, da man nur noch allokiert ohne freizugeben.

Gute GCs sind im allgemeinen bei etwa 30% des dynamisch genutzten Speichers als Mehrverbrauch genauso schnell wie manuelle Speicherverwaltung.
ob 30% stimmt weiss ich nicht, aber an sich stimmt es, dass eine gute speicherverwaltung erst unter druck zeigen muss was sie leistet.
Eine generalisierte speicherverwaltung reicht auch nicht in jedem fall bei c++, da muss man zur not eigene allokatoren schreiben.
Wie ich schon schrieb, ist das bei Java-handy-spielen auch so. damit will ich sagen, wenn es kritisch wird, kommt es doch auf handarbeit an. in dem fall ist es, falls man damit nicht von anfang an gerechnet hat, schoen wenn sowas von der sprache erlaubt wird.

Trap
2007-10-10, 12:55:49
wenn beiden gleich viel speicher zur verfuegung steht (also z.b. unendlich) hast du gleiche geschwindigkeit, da man nur noch allokiert ohne freizugeben.
Unendlich viel Speicher gibt es aber nicht. Nahezu unendlich wäre z.B. 1 MB genutzt bei 8 GB verfügbar und das Programm lange genug läuft, dass nie freigeben nicht funktioniert.

Gast
2007-10-10, 13:01:27
Und die verbrauchen keine Prozesszeit?

Darum geht's überhaupt nicht. Dass eine Speicherverwaltung der VM ebenfalls Prozessorzeit braucht ist klar. Aber bei C++ findet die Speicherverwaltung eben recht sequentiell mit dem Programmablauf statt, d.h. dann, wenn man tatsächlich Speicher allokiert. Damit bringt man sich automatisch in Schwierigkeiten, da man nämlich die Speicherverwaltung an feste Zeitpunkte (wenn man im Code Speicher allokieren will) bindet. Wenn aber z.B. eine Heap Defragmentierung in einem Hintergrundthread stattdindet, kann die VM wesentlich intelligenter ins Spiel eingreifen. Wenn dein Programm zu 100% alle CPU Zyklen verwendet, dann wäre wahrscheinlich die VM Version genau so langsam wie manuelle Speicherverwaltung. Da dies aber bei 99% aller Desktopanwendungen eh nicht der Fall ist, ist dieses Szenario für die meisten Anwendungen irrelevant.

micki
2007-10-10, 13:06:01
Unendlich viel Speicher gibt es aber nicht. Nahezu unendlich wäre z.B. 1 MB genutzt bei 8 GB verfügbar und das Programm lange genug läuft, dass nie freigeben nicht funktioniert.
so limitiert ist ploetzlich unendlich :)
aber in beiden faellen waere die speicherverwaltung frueher oder spaeter am arbeiten.

micki
2007-10-10, 13:18:23
Darum geht's überhaupt nicht. Dass eine Speicherverwaltung der VM ebenfalls Prozessorzeit braucht ist klar. Aber bei C++ findet die Speicherverwaltung eben recht sequentiell mit dem Programmablauf statt, d.h. dann, wenn man tatsächlich Speicher allokiert. Damit bringt man sich automatisch in Schwierigkeiten, da man nämlich die Speicherverwaltung an feste Zeitpunkte (wenn man im Code Speicher allokieren will) bindet.kannst du erleutern wieso eine on-demand speicherverwaltung schwierigkeiten impliziert gegenueber einer die die selbe arbeit in einem anderen thread macht?

Wenn aber z.B. eine Heap Defragmentierung in einem Hintergrundthread stattdindet, kann die VM wesentlich intelligenter ins Spiel eingreifen. Wenn dein Programm zu 100% alle CPU Zyklen verwendet, dann wäre wahrscheinlich die VM Version genau so langsam wie manuelle Speicherverwaltung.
da in solchen faellen gezielte speicherverwaltungs-algorithmen verwendet werden, gibt es in so ziemlich keinem c++ program eine defragmentation, das waere viel zu langsam. klar macht das eine VM die ganze zeit im hintergrund. wenn du glueck hast, zieht das nur kontinuirlich 5% performance. statt also etwas mehr aufwand zu haben (aufwand im sinne von programmieraufwand einer besonderen speicherverwaltung), hast du im hintergrund die ganze zeit eine speicherverwaltung die speicher durch die gegend schiebt, etwas wofuer man bei zeitkritischen applikationen nie zeit verschwenden wollen wuerde.

Da dies aber bei 99% aller Desktopanwendungen eh nicht der Fall ist, ist dieses Szenario für die meisten Anwendungen irrelevant.
klar, in applikationen in denen speicherverwaltung irrelevant ist, weil man genug rechenzeit vorhanden ist, hat man weder mit defered noch mit on-demand speicherverwaltung probleme. da ist dann eine VM genau so recht wie es selbst zu machen.
aber performance will man ja gerade in kritischen faellen haben, und es duerfte sehr selten vorkommen, dass ein programm total zeit unkritisch unmengen an daten ansammelt, dann lang genug idle ist damit eine VM die daten umordnet kann, um dann wieder mit voller last die daten abzuarbeiten.

Trap
2007-10-10, 13:22:56
so limitiert ist ploetzlich unendlich :)
aber in beiden faellen waere die speicherverwaltung frueher oder spaeter am arbeiten.
Ja, nur ist die Arbeit für den GC nur von den lebendigen Objekten abhängig und die soll ja nach Annahme gleich bleiben, je seltener also der GC anspringt desto weniger CPU-Zeit braucht er insgesamt.

Manuelle Speicherverwaltung wie sie üblicherweise gemacht wird, mit direktem Löschen sobald ein Objekt unerreichbar wird, braucht Aufwand proportional zur Anzahl der toten Objekte und hat keinen Vorteil durch den zusätzlichen Speicher.

Gast
2007-10-10, 13:33:40
kannst du erleutern wieso eine on-demand speicherverwaltung schwierigkeiten impliziert gegenueber einer die die selbe arbeit in einem anderen thread macht?


Habe ich doch gesagt. Du bist an die vorbestimmte Zeit gebunden, wenn die Speicherverwaltung stattfindet. Und die findet statt, wenn du Speicher allokierst. D.h. wiederum, je mehr Speicher du intensiver allokierst, desto intensiver macht sich auch die aufwendige Verwaltung bei der Allokation bemerkbar.


klar macht das eine VM die ganze zeit im hintergrund.


Das macht die VM eben NICHT die ganze Zeit im Hintergrund, sondern nach bestimmten Algorithmen, die wiederum auf bestimmten Statistiken basieren (wann im Code allokiert wird usw.).


klar, in applikationen in denen speicherverwaltung irrelevant ist, weil man genug rechenzeit vorhanden ist, hat man weder mit defered noch mit on-demand speicherverwaltung probleme.


Ich sehe keinen Zusammenhang zwischen Prozessorauslastung und Speicherverbrauch.

Gast
2007-10-10, 13:55:37
Ja, nur ist die Arbeit für den GC nur von den lebendigen Objekten abhängig und die soll ja nach Annahme gleich bleiben, je seltener also der GC anspringt desto weniger CPU-Zeit braucht er insgesamt.nein, desto seltener braucht es die cpu zeit, dafuer aber mehr auf einmal.

Gast
2007-10-10, 14:01:34
Habe ich doch gesagt. Du bist an die vorbestimmte Zeit gebunden, wenn die Speicherverwaltung stattfindet. Und die findet statt, wenn du Speicher allokierst. D.h. wiederum, je mehr Speicher du intensiver allokierst, desto intensiver macht sich auch die aufwendige Verwaltung bei der Allokation bemerkbar.ja, bei der allokation. aber in der gesamtlaufzeit des programms bleibt es gleich viel aufwand. denn das kommt auch auf die VM zu, sie macht ja nichts wenn du nicht allokierst/deallokierst. aber je mehr du das machst, desto mehr speicherverwaltungsarbeit muss die VM beweltiken. eine VM spart keine laufzeit oder arbeit, sie macht es nur defered.



Das macht die VM eben NICHT die ganze Zeit im Hintergrund, sondern nach bestimmten Algorithmen, die wiederum auf bestimmten Statistiken basieren (wann im Code allokiert wird usw.).ja, aber sie muss diese arbeit machen, aufgrund ihrer statistiken, genau so wie ein c++ programm diese arbeit machen muss, aufgrund von von menschen ausgesuchten algorithmen.



Ich sehe keinen Zusammenhang zwischen Prozessorauslastung und Speicherverbrauch.
Wenn dein Programm zu 100% alle CPU Zyklen verwendet, dann wäre wahrscheinlich die VM Version genau so langsam wie manuelle Speicherverwaltung.diese korelation hat ein gast vorhin geschrieben.

Gast
2007-10-10, 14:15:23
denn das kommt auch auf die VM zu, sie macht ja nichts wenn du nicht allokierst/deallokierst.


Natürlich macht sie dann auch was, das ganze wäre sonst recht witzlos.


ja, aber sie muss diese arbeit machen, aufgrund ihrer statistiken, genau so wie ein c++ programm diese arbeit machen muss, aufgrund von von menschen ausgesuchten algorithmen.


Und das kann sie dann auch bei Codeteilen nebenbei machen, wo keine großen Speicher Allokationen stattfinden.


diese korelation hat ein gast vorhin geschrieben.

Und wurde als vollkommen praxisfremd zu recht tituliert.

Gast
2007-10-10, 14:35:53
Natürlich macht sie dann auch was, das ganze wäre sonst recht witzlos.also kein laufzeitvorteil durch eine VM wenn bei beiden programmen die gleiche arbeit erledigt wird.



Und das kann sie dann auch bei Codeteilen nebenbei machen, wo keine großen Speicher Allokationen stattfinden. es ist egal ob sie das waehrend grosser speicherallokationen macht oder zwischendurch wenn ueberhaupt keine vorhanden sind. es kostet weiterhin die selbe prozesszeit. wo ist da der geschwindigkeitsvorteil in performancekritischen programmen?



Und wurde als vollkommen praxisfremd zu recht tituliert.
was ich nochmals bekraeftigte und darauf hinwies, dass wir hier ueber die geschwindigkeit von programmen reden. nicht von programmen die eh keine rechenzeit ziehen bei denen die geschwindigkeit durch die speicherverwaltung egal ist.

Trap
2007-10-10, 14:36:16
nein, desto seltener braucht es die cpu zeit, dafuer aber mehr auf einmal.
Du hast keine Ahnung wie ein GC funktioniert.

micki
2007-10-10, 14:50:27
Du hast keine Ahnung wie ein GC funktioniert.
Ich weiss dass es nicht DEN GC gibt und ich weiss wie recht viele implementierungen funktionieren. Viele haben eine sehr schoenes Laufzeitverhalten (was die O notation betrifft), aber die wirklichen laufzeitkosten sind dennoch nicht weniger als in den on-demand speicherverwaltungen (oft sogar schlechter).

Grestorn
2007-10-10, 14:51:51
Ich weiss dass es nicht DEN GC gibt und ich weiss wie recht viele implementierungen funktionieren. Viele haben eine sehr schoenes Laufzeitverhalten (was die O notation betrifft), aber die wirklichen laufzeitkosten sind dennoch nicht weniger als in den on-demand speicherverwaltungen (oft sogar schlechter).

Der Vorteil eines GC ist, dass er nebenläufig ist, d.h. Prozessorzeit auch dann nutzt, wenn sie nicht von der eigentlichen Anwendung benötigt wird.

Gast
2007-10-10, 14:53:47
also kein laufzeitvorteil durch eine VM wenn bei beiden programmen die gleiche arbeit erledigt wird.


Doch, den gibt es ganz klar.


es ist egal ob sie das waehrend grosser speicherallokationen macht oder zwischendurch wenn ueberhaupt keine vorhanden sind. es kostet weiterhin die selbe prozesszeit. wo ist da der geschwindigkeitsvorteil in performancekritischen programmen?


Die Mehrheit aller Programme in der Praxis sind aber kein Daumenkino, die vom Anfang bis Ende ablaufen und 100% CPU Auslastung erzeugen. Genau das wäre nämlich ein Szenario, wo die VM keine Vorteile hätte.


was ich nochmals bekraeftigte und darauf hinwies, dass wir hier ueber die geschwindigkeit von programmen reden.

Wir reden hier von der Allokationsgeschwindigkeit! Du redest die ganze Zeit von irgendwelchen Ausnahmesituationen. Zwischen dem Speicherverbrauch einer Anwendung und der möglichen Prozessorauslastung, die durch die Anwendungslogik entsteht, gibt es erst mal keinen direkten Zusammenhang.

micki
2007-10-10, 14:58:12
Der Vorteil eines GC ist, dass er nebenläufig ist, d.h. Prozessorzeit auch dann nutzt, wenn sie nicht von der eigentlichen Anwendung benötigt wird.
jap, aber wie wir hier schon geklaert haben, ist in einem fall in dem die applikation die cpu nicht voll ausnutzt, diese applikation wohl auch nicht performancekritisch und somit ist (siehe gast) das hier irrelevant.

micki
2007-10-10, 15:05:15
Die Mehrheit aller Programme in der Praxis sind aber kein Daumenkino, die vom Anfang bis Ende ablaufen und 100% CPU Auslastung erzeugen. Genau das wäre nämlich ein Szenario, wo die VM keine Vorteile hätte.ja, nur sind solche applikationen auch kein punkt an dem man performance misst.



Wir reden hier von der Allokationsgeschwindigkeit! Du redest die ganze Zeit von irgendwelchen Ausnahmesituationen.ich rede davon, dass wenn eine applikation performancekritisch ist, ist allokationsgeschwindigkeit nicht von der ganzen speicherverwaltung zu entkoppeln. egal ob deferred oder nicht. wenn dein program 10min auf hochlast laeuft und die ganze zeit allokiert und freigibt, ist es vollkommen egal ob sofort speicher freigegeben wird oder erst ein thread im hintergrund den speicher in die verwaltung aufnimmt, die arbeit wird waehrend der 10min gemacht werden muessen, falls man nicht gerade bei einem programm das peak maximal 1MB zieht, sich 8GB durch die VM reservieren laesst fuer solche faelle.

Grestorn
2007-10-10, 15:08:35
jap, aber wie wir hier schon geklaert haben, ist in einem fall in dem die applikation die cpu nicht voll ausnutzt, diese applikation wohl auch nicht performancekritisch und somit ist (siehe gast) das hier irrelevant.

Auch performancekritische Anwendungen verbrauchen im normalfall nicht ständig 100% Leistung, sondern eben nur in kritischen Situationen.

Gast
2007-10-10, 15:14:53
jap, aber wie wir hier schon geklaert haben, ist in einem fall in dem die applikation die cpu nicht voll ausnutzt, diese applikation wohl auch nicht performancekritisch und somit ist (siehe gast) das hier irrelevant.

Dreh dir doch die Dinge nicht immer so zurecht, wie dir das gerade gefällt. Wir haben hier anfänglich von Allokationsgeschwindigkeiten gesprochen. Und die absolute Mehrheit von allen Desktop-Programmen braucht auch nicht konstante 100% CPU Leistung, insofern sind deine Ausnahmesituationen irrelevant. Auf der anderen Seite heißt das nicht, dass Anwendungen mit VM nicht performancekritisch sein können.

micki
2007-10-10, 15:16:06
Auch performancekritische Anwendungen verbrauchen im normalfall nicht ständig 100% Leistung, sondern eben nur in kritischen Situationen.
dem kann ich nicht ganz folgen.
koenntest du mir ein beispiel geben an dem eine performancekritische anwendung speicher weit im vorraus allokiert, mit dem sie erst viel spaeter ihre performancekritischen dinge macht? was mich eigentlich irritiert ist, wie das mit der allokationsgeschwindigkeit dann zusammenhaengt
das was ich mir im entferntesten darunter vorstellen koennte waere eine Datenbank, aber gerade die haben eigene speicherverwaltungen weil die generischen ihnen nicht gerecht werden.
Ein bildverarbeitungsprogramm? aber auch die allokieren kurz davor ihre daten auf denen sie dann auch arbeiten (zudem haben diese ebenfalls eigene speicherverwaltungen und manchmal sogar auslagerungsmechanismen, siehe photoshop)
bitte um ein beispiel.

micki
2007-10-10, 15:24:59
Dreh dir doch die Dinge nicht immer so zurecht, wie dir das gerade gefällt. Wir haben hier anfänglich von Allokationsgeschwindigkeiten gesprochen. ich weiss nicht ueber welches thema du sprechen willst. ich spreche ueber das vom threadstarter, bei dem 'hellhorse' sagte, dass direkte speicherverwaltung langsammer waere. er hat nicht nur die allokationszeit angesprochen. zur verwaltung gehoert weit aus mehr.

Und die absolute Mehrheit von allen Desktop-Programmen braucht auch nicht konstante 100% CPU Leistung, insofern sind deine Ausnahmesituationen irrelevant.
es geht hier nicht um applikationen oder momente in denen keine cpu-zeit gefordert wird. es geht um den moment an dem performance wichtig ist und (wie ihr hier noch hinzugefuegt habt) im besonderen wenn dabei viel allokiert/freigegeben wird.
dabei jukt es nicht wenn ein program mal 1s oder 1.0001s braucht wegen speicherallokationen, wenn es sonst 99% der zeit nicht performancekritisch ist, sondern wie die performance ist bei performancekritischen applikationen.
eure argumentation mit 'VM ist schneller bei applikationen die eh nie performancekritisch sind' sind doch wie putzen von sauberen fenstern. void.

Gast
2007-10-10, 15:41:36
ich weiss nicht ueber welches thema du sprechen willst. ich spreche ueber das vom threadstarter, bei dem 'hellhorse' sagte, dass direkte speicherverwaltung langsammer waere. er hat nicht nur die allokationszeit angesprochen. zur verwaltung gehoert weit aus mehr.


Nö, du hast hier vom dummen Marketing gesprochen als kürzere Allokationszeiten bei VM verwalteten Speicher angesprochen wurde. Ich habe manchmal den Eindruck, dass du gar nicht so recht weißt, was du die ganze Zeit erzählst.


es geht hier nicht um applikationen oder momente in denen keine cpu-zeit gefordert wird. es geht um den moment an dem performance wichtig ist und (wie ihr hier noch hinzugefuegt habt) im besonderen wenn dabei viel allokiert/freigegeben wird.


Nö, darum geht es gar nicht. Du redest nur die ganze Zeit davon. Das ändert auch weiterhin nichts daran, dass die Allokationszeiten bei normaler/hoher CPU Last immer noch schneller ist als deine Spezialfälle.


eure argumentation mit 'VM ist schneller bei applikationen die eh nie performancekritisch sind' sind doch wie putzen von sauberen fenstern. void.

Und deine Argumentation, dass hoher Speicherverbrauch nur mit hoher CPU Auslastung einhergeht ist auch wie putzen von sauberen Fenstern. void

micki
2007-10-10, 15:47:36
Nö, du hast hier vom dummen Marketing gesprochen als kürzere Allokationszeiten bei VM verwalteten Speicher angesprochen wurde. Ich habe manchmal den Eindruck, dass du gar nicht so recht weißt, was du die ganze Zeit erzählst.
Ein Grund dafür?!? Direkte Speicherverwaltung ist langsam, fehleranfällig und mühsam.deiner kristalkugel sollte die marketingmodifikation entfernt bekommen. ich sehe nichts von allokationzeit in seinem satz.




Nö, darum geht es gar nicht. Du redest nur die ganze Zeit davon. Das ändert auch weiterhin nichts daran, dass die Allokationszeiten bei normaler/hoher CPU Last immer noch schneller ist als deine Spezialfälle.dem stimm ich auch voll zu, siehe mein 'kiesel in tuete' beispiel.



Und deine Argumentation, dass hoher Speicherverbrauch nur mit hoher CPU Auslastung einhergeht ist auch wie putzen von sauberen Fenstern. void mein beispiel mit '1MB' bei vollauslastung ist weiss gott kein hoher speicherverbrauch.

Gast
2007-10-10, 15:51:35
ich sehe nichts von allokationzeit in seinem satz.


Stell dich doch nicht so dumm an! Deine Vorfürfe bzgl. dummen Marketing hast du auch nicht auf Hellhorse bezogen.


Bin zwar ein anderer Gast, aber das ist im Allg. bekannt, dass dynam. Speicher i.d.R. fast genau so schnell wie vom Stack allokiert werden kann, weil die VM die Verwaltung im Hintergrund übernimmt. Wenn du ein neues Objekt auf dem Heap anlegst, hat die VM schon einen Zeiger auf genügend freien Speicher. Und falls das mal nicht so ist (also Zeiger + Datenstrukturgröße > Heap/Generation) wird die Garbage Collection gestartet.
das ist eben die dumme marketing argumentation die alle die nicht drueber nachdenken davon ueberzeugt dass es viel schneller ist. um es mal auf ein anderes model zu bilden.

Gast
2007-10-10, 15:54:52
mein beispiel mit '1MB' bei vollauslastung ist weiss gott kein hoher speicherverbrauch.

Warum sollte da sich überhaupt die VM wegen 1MB bemühen zu collceton/defragmentieren?

Nasenbaer
2007-10-10, 16:01:19
@micki

Es geht hier um Ressourcenkonflikte, die der Prozess-Scheduler ausnutzen kann wodurch eine Beschleunigung mittels ausgelagerter Speicherverwaltung, sprich VM, ermöglicht werden kann.
Beispiel:
Programm A hat nicht mehr benötigten Speicher und rechnet gerade CPU-intensiv irgendwas aus ohne großartigt Speicherzugriffe zu benötigen.

Programm B (die VM) sorgt derweil für die Freigabe des Speichers. Sie kann auf ihn zugreifen, da Programm A den Zugriff nicht benötigt.

Bei pseudoparallelen Rechnern sicher nicht von Vorteil, da gleichzeitig eh nur ein Programm arbeiten kann aber in Zeiten von Dual-, Triple-, Quad-Core sicher nicht unwarscheinlich, dass Programm und VM vollständig parallel laufen können.

Programm A könnte aber auch gerade auf Informationen warten, z.B. User-eingaben, Netzwerkdaten, Festplattenzugriffe, etc. und während dessen lässt der Scheduler die VM den Speicher befreien. Bei Betriebssystemen die keinerlei Parallelität ermöglichen bringt es genau 0% verbesserung aber solche Betriebssysteme sind höchstens in hochintegrierten Systemen im einsatz und da nutzt man dann eh keine VM.

micki
2007-10-10, 16:04:37
Stell dich doch nicht so dumm an! Deine Vorfürfe bzgl. dummen Marketing hast du auch nicht auf Hellhorse bezogen.
doch habe ich, und die eklaerung vom gast weshalb die speicherverwaltung schneller ist, sagte als eklaerung dass sie schneller ist weil die allokationszeit schneller ist, worauf ich das als eben das marketing-BS bezeichnete, die bei der speicherverwaltung die zeit vom GC unterm tisch fallen laesst.

das bisschen transferleistung haettest du aber auch selbst bringen koennen, bevor du andere der dummstellung bezichtigst weil du etwas nicht erfasst.

micki
2007-10-10, 16:07:18
Warum sollte da sich überhaupt die VM wegen 1MB bemühen zu collceton/defragmentieren?
1MB peak verbrauch, aber sehr viel allokationen-dealokationen. sodass du am ende nicht viel durchschnittsverbrauch hast, jedoch je nach speicherverwaltung viel an deallokations-speicher angestaut werden koennte, wenn die speicherverwaltung es erst deferred freigibt. was eben ein vorteil einer VM ist bei mit unendlich viel speicher, siehe:
http://www.forum-3dcenter.org/vbulletin/showpost.php?p=5918767&postcount=46

micki
2007-10-10, 16:19:31
Es geht hier um Ressourcenkonflikte, die der Prozess-Scheduler ausnutzen kann wodurch eine Beschleunigung mittels ausgelagerter Speicherverwaltung, sprich VM, ermöglicht werden kann.
Beispiel:
Programm A hat nicht mehr benötigten Speicher und rechnet gerade CPU-intensiv irgendwas aus ohne großartigt Speicherzugriffe zu benötigen.

Programm B (die VM) sorgt derweil für die Freigabe des Speichers. Sie kann auf ihn zugreifen, da Programm A den Zugriff nicht benötigt.

Bei pseudoparallelen Rechnern sicher nicht von Vorteil, da gleichzeitig eh nur ein Programm arbeiten kann aber in Zeiten von Dual-, Triple-, Quad-Core sicher nicht unwarscheinlich, dass Programm und VM vollständig parallel laufen können.klar, das ist natuerlich ein grosser vorteil, man kann ja nicht unendlich parallelisieren, somt koennte 'verschleisszeit' fuer andere dinge verwendet werden.
Oft ist das problem jedoch, dass programme die viel cpu-auslastung haben, nur wenig von der idlezeit liefern, selbst wenn sie schlecht parallelisiert sind, weil sie z.b. in spinlocks warten. Das ist natuerlich nicht der fall wenn ueber OS-spezifische Mutex/Signals gearbeitet wird, jedoch ist die applikation dann auch schon von soviel overhead gepraegt, dass wohl kaum optimiert gearbeitet wird.

Programm A könnte aber auch gerade auf Informationen warten, z.B. User-eingaben, Netzwerkdaten, Festplattenzugriffe, etc. und während dessen lässt der Scheduler die VM den Speicher befreien. Bei Betriebssystemen die keinerlei Parallelität ermöglichen bringt es genau 0% verbesserung aber solche Betriebssysteme sind höchstens in hochintegrierten Systemen im einsatz und da nutzt man dann eh keine VM.
solche systeme koennen aber auch, statt nur zu warten, im hintergrund schon ihre arbeit machen. z.b. Eclips dass im hintergrund die ganze zeit compiliert oder Irfanview dass schon bilder im voraus dekodiert. Wenn es etwas zeitkritisches ist, wird man wenig idlezeit haben denk ich mir. wenn doch, dann hast du natuerlich recht. Nur muss man dann sehen wieviel speicher man bei einer speicher-allokations/deallokations intensiven applikation waehrend der vollen cpu-auslastung anstauen kann.
ich hab so die erfahrung, dass sobald eine applikation irgendwie durch speicherallokationen performanceeinbussen hat und merklich performancekritisch ist, die menge des verwendeten speichers (selbst bei kleinstallokationen) ueber das moegliche steigt was eine VM cached.

Gast
2007-10-10, 16:30:35
doch habe ich, und die eklaerung vom gast weshalb die speicherverwaltung schneller ist, sagte als eklaerung dass sie schneller ist weil die allokationszeit schneller ist, worauf ich das als eben das marketing-BS bezeichnete, die bei der speicherverwaltung die zeit vom GC unterm tisch fallen laesst.


Unglaublich, was du hier abziehst. Du bist sofort auf mein Thema mit den Allokationszeiten angesprungen und weißt jetzt plötzlich nicht mehr wovon du redest. Damit ist dann der Thread für mich eben gestorben. Ich bin schließlich nicht daran interessiert, mich mit deinem Ego zu messen.


das bisschen transferleistung haettest du aber auch selbst bringen koennen, bevor du andere der dummstellung bezichtigst weil du etwas nicht erfasst.

Achso, jetzt bist du wieder das Unschuldslamm. Du hast hier mit dummen Marketing um dich geworfen, mit Kristallkugeln, mit Leichtgläubigen, die keine Ahnung von Grundlagenphysik haben usw.

micki
2007-10-10, 16:43:28
Du bist sofort auf mein Thema mit den Allokationszeiten angesprungen und weißt jetzt plötzlich nicht mehr wovon du redest.
sorry gast, aber du bist auf mein marketing ist bullshit aufgesprungen:
http://www.forum-3dcenter.org/vbulletin/showpost.php?p=5916291&postcount=35

Achso, jetzt bist du wieder das Unschuldslamm. Du hast hier mit dummen Marketing um dich geworfen, mit Kristallkugeln, mit Leichtgläubigen, die keine Ahnung von Grundlagenphysik haben usw.was hat das jetzt mit deinem quote zu tun dass du die transferleistung nicht erbracht hast?

Gast
2007-10-10, 16:45:28
sorry gast, aber du bist auf mein marketing ist bullshit aufgesprungen:
http://www.forum-3dcenter.org/vbulletin/showpost.php?p=5916291&postcount=35


Das war ein anderer Gast. Ich habe ja auch geschrieben:

Bin zwar ein anderer Gast, aber das ist im Allg. bekannt, dass dynam. Speicher i.d.R. fast genau so schnell wie vom Stack allokiert werden kann, weil die VM die Verwaltung im Hintergrund übernimmt. Wenn du ein neues Objekt auf dem Heap anlegst, hat die VM schon einen Zeiger auf genügend freien Speicher. Und falls das mal nicht so ist (also Zeiger + Datenstrukturgröße > Heap/Generation) wird die Garbage Collection gestartet.

Also hast du folglich mich ganz klar gequotet.

micki
2007-10-10, 16:54:55
Das war ein anderer Gast.sorry, aber wie soll ich euch alle auseinander halten? ich weiss noch nichtmal welcher gerade antwortet und mit wievielen ich hier rede. deine anforderungen an meine faehigkeit der differenzierung uebersteigt meine faehigkeiten bei weiten, es kostet euch nur ein paar tasten um euch auch als gast differenzierbar zu halten. wenn auch daran wert laege, wurdet ihr das machen. aber regt euch nicht auf dass ich mir kein log mache welcher gast nun was gesagt haben kann.

ich spreche hier grundsaetzlich ueber das topic im anschluss an die aussage Hellhorse' dass speicherverwaltung mit VMs schneller sein soll, bzw ueber die Milchmaenchen rechnungen der Marketingabteilungen die die RC zeit aus der speicherverwaltung rausrechnen und wegen schnellen allokationen auf schnelle applikationen zurueckfolgern, dem nicht so ist.

Grestorn
2007-10-10, 18:53:31
dem kann ich nicht ganz folgen.
koenntest du mir ein beispiel geben an dem eine performancekritische anwendung speicher weit im vorraus allokiert, mit dem sie erst viel spaeter ihre performancekritischen dinge macht?

Das wird sie sicher nicht tun.

Aber der GC legt los, wenn die App gerade mal wenig zu tun hat, und schaufelt so Speicher für die nächste Allokation frei.

Man spart sich also die Freigabe des Speichers im Rahmen des normalen Programmablauf, wo sie theoretisch deutlich mehr stört, als wenn der Prozess eh die CPU nicht auslastet.

Bei der Speicherallokation kann man mit einem GC nicht sparen, denn darum kümmert sich der GC ja schließlich auch nicht ;)

Gast
2007-10-10, 19:12:48
ich spreche hier grundsaetzlich ueber das topic im anschluss an die aussage Hellhorse' dass speicherverwaltung mit VMs schneller sein soll, bzw ueber die Milchmaenchen rechnungen der Marketingabteilungen die die RC zeit aus der speicherverwaltung rausrechnen und wegen schnellen allokationen auf schnelle applikationen zurueckfolgern, dem nicht so ist.

Wieso? Das wurde doch jetzt hinlänglich deutlich gemacht, dass dem so ist (Allokationszeit). Dass es vielleicht unter bestimmten Bedingungen nicht so ist, ändert ja nichts daran.

Gast
2007-10-10, 19:14:34
^^ Wenn man noch im Allgmeinfall davon ausgeht, dass genügend CPU Zyklen für das collecten vorhanden sind.

ScottManDeath
2007-10-10, 19:21:34
Mein Raytracer alloziert am Anfang einige 100 MB waehrend der Erstellung der Datenstrukturen fuer meine Meshes, dann kommt der GC und raeumt auf was ich nicht mehr brauche. Danach crunche ich fuer ein paar Stunden mit sogut wie keiner dynamischen Speicherallozierung.

HellHorse
2007-10-10, 21:22:33
deiner kristalkugel sollte die marketingmodifikation entfernt bekommen.
Stimmt, die wahren Gründe gegen manuelle Speicherveraltung wie in C++ sind:
- Extrem unsicher, 50% aller Sicherheitslücken sind Bufferoverflows.
- So unglaublich schwer das selbst Profis mit jahrelanger Erfahrung es regelmässig verhauen. Such dir irgend einen Hersteller aus, der es "drauf" haben sollte, Microsoft, Apple, Linux ganz egal, such dir irgend eine beliebige C oder C++ library aus. Mit an Sicherheit grenzender Wahrscheinlichkeit hatte sie schon mal einen Bufferoverflow oder ein memory leak. Irgendwann müssen wir aufhören uns einzureden es gäbe einen Programmierer der manuelle Speicherverwaltung hinkriegt und der Realität ins Auge blicken.

Gast
2007-10-11, 07:58:06
und die meisten studenten wuerden wahrscheinlich auch rausfinden dass c++ 100mal schneller als assembler ist wenn sie es benchen... das sagt in dem fall nur aus, wie gut der programmierer ist und gleichzeitig dass er dann nicht assembler nehmen sollte *hehe*. Bis man ein gegenüber C++ 100x langsameres ASM Programm fertigstellt, hört man vorher sowieso auf.

Ganon
2007-10-11, 13:30:26
Stimmt, die wahren Gründe gegen manuelle Speicherveraltung wie in C++ sind:
- Extrem unsicher, 50% aller Sicherheitslücken sind Bufferoverflows.
- So unglaublich schwer das selbst Profis mit jahrelanger Erfahrung es regelmässig verhauen. Such dir irgend einen Hersteller aus, der es "drauf" haben sollte, Microsoft, Apple, Linux ganz egal, such dir irgend eine beliebige C oder C++ library aus. Mit an Sicherheit grenzender Wahrscheinlichkeit hatte sie schon mal einen Bufferoverflow oder ein memory leak. Irgendwann müssen wir aufhören uns einzureden es gäbe einen Programmierer der manuelle Speicherverwaltung hinkriegt und der Realität ins Auge blicken.

Jup. Selbst von Leuten die sich Sicherheit groß an die Backe schreiben, fabrizieren u.a. so etwas:

Gerade frisch von OpenBSD:
http://www.heise.de/newsticker/meldung/97226

Ist zwar keine Sicherheitslücke in dem Sinne, aber es ist im Prinzip das Gleiche, kann halt nur nicht genutzt werden.

micki
2007-10-16, 12:24:47
Stimmt, die wahren Gründe gegen manuelle Speicherveraltung wie in C++ sind:
- Extrem unsicher, 50% aller Sicherheitslücken sind Bufferoverflows.
- So unglaublich schwer das selbst Profis mit jahrelanger Erfahrung es regelmässig verhauen. Such dir irgend einen Hersteller aus, der es "drauf" haben sollte, Microsoft, Apple, Linux ganz egal, such dir irgend eine beliebige C oder C++ library aus. Mit an Sicherheit grenzender Wahrscheinlichkeit hatte sie schon mal einen Bufferoverflow oder ein memory leak. Irgendwann müssen wir aufhören uns einzureden es gäbe einen Programmierer der manuelle Speicherverwaltung hinkriegt und der Realität ins Auge blicken.
Wir wollten uns auch aufhoeren einzureden dass eine VM oder ein GC vor solchen fehlern schuetzen. Oft entstehen sie naemlich auf algorithmischer ebene, deswegen gibt es ja in der sprache ohne pointer eine nullpointer exception.

Bis man ein gegenüber C++ 100x langsameres ASM Programm fertigstellt, hört man vorher sowieso auf.dann hast du wohl den grossen performance-vergleich-artikel von der c't verpasst in dem sie c++ vs ... getestet haben und sowas von schlimme fehler machten .... es ist nicht schwer einen 100mal langsameren code zu schreiben, wenn man sorgenfrei an die sache geht und hofft dass die magic im hintergrund die sache schon richten wird. siehst du ja am threadstarter.

Demirug
2007-10-16, 13:10:08
Wir wollten uns auch aufhoeren einzureden dass eine VM oder ein GC vor solchen fehlern schuetzen. Oft entstehen sie naemlich auf algorithmischer ebene, deswegen gibt es ja in der sprache ohne pointer eine nullpointer exception.

Natürlich schützen eine VM und ein GC nicht vor allen Fehlern aber es ist viel einfacher sie aufzuspüren. Und den schlimmsten aller C++ Fehler kannst du in C# nicht produzieren: „Wild Pointers“.

Bietchiebatchie
2007-10-16, 14:22:20
Stimmt, die wahren Gründe gegen manuelle Speicherveraltung wie in C++ sind:
- Extrem unsicher, 50% aller Sicherheitslücken sind Bufferoverflows.
- So unglaublich schwer das selbst Profis mit jahrelanger Erfahrung es regelmässig verhauen. Such dir irgend einen Hersteller aus, der es "drauf" haben sollte, Microsoft, Apple, Linux ganz egal, such dir irgend eine beliebige C oder C++ library aus. Mit an Sicherheit grenzender Wahrscheinlichkeit hatte sie schon mal einen Bufferoverflow oder ein memory leak. Irgendwann müssen wir aufhören uns einzureden es gäbe einen Programmierer der manuelle Speicherverwaltung hinkriegt und der Realität ins Auge blicken.

Wir wollten uns auch aufhoeren einzureden dass eine VM oder ein GC vor solchen fehlern schuetzen. Oft entstehen sie naemlich auf algorithmischer ebene, deswegen gibt es ja in der sprache ohne pointer eine nullpointer exception.

Hö? Genau vor Bufferoverflows und Memoryleaks schützt dich die VM / Runtime.

@Topic:
Speed ist so dermaßen overrated...
Ich würde C# auch nutzen wenn es 10mal langsamer wäre - und wahrscheinlich nichtmal großartig einen Unterschied bemerken.

micki
2007-10-16, 15:45:26
Natürlich schützen eine VM und ein GC nicht vor allen Fehlern aber es ist viel einfacher sie aufzuspüren. Und den schlimmsten aller C++ Fehler kannst du in C# nicht produzieren: „Wild Pointers“.
ein pointer ist nur ein index im speicher, solange du indizieren kannst, kannst du wild pointer haben.

micki
2007-10-16, 15:47:37
Hö? Genau vor Bufferoverflows
nur wenn du arrays verbietest, ansonsten kannst du immer einen overflow haben, wenn auch nur im scope vom array.

und Memoryleaks schützt dich die VM / Runtime.
solange du auf objekte referenzierst, hilft dir eine VM nicht dieses leak zu finden. ich hab schon serverapplikationen gesehen (java) die alle 24h neu gestartet wurden wegen solcher leaks.

Demirug
2007-10-16, 15:50:01
ein pointer ist nur ein index im speicher, solange du indizieren kannst, kannst du wild pointer haben.

Nicht in einem strong typed system.

micki
2007-10-16, 16:02:05
Nicht in einem strong typed system.
auch dann, ist das moeglich.

stell dir nur vor du hast ein array von textureresourcen und jemand ist so smart speicher zu sparen indem er sich nur eine 16bit ID drauf speichert (also den index). dann loescht das system die texture (wesehalb auch immer), somit hast du nun einen wilden pointer (damit mein ich nicht den vom array auf das objekt, denn der ist nun auf null, sondern die ID). allokierst du nun ein neues objekt an die selbe stelle im array (z.b. animierte textur die von texture abgeleitet war) ist der pointer weiterhin "wild" und arbeitet nun ploetzlich auf nem voellig falschen objekt.

edit: alternativ kann ich dir natuerlich auch einen uninitialisierten index bieten ;)

Demirug
2007-10-16, 16:13:49
Sowas würde ich nicht als „wild pointer“ bezeichnen. Zudem sind solche Fehler leicht zu finden. Richtige „wild pointer“ Fehler sind sehr schwer zu finden.

micki
2007-10-16, 16:20:51
Sowas würde ich nicht als „wild pointer“ bezeichnen.
also nicht ein undefiniert in der welt indizierender wert?


Zudem sind solche Fehler leicht zu finden. Richtige „wild pointer“ Fehler sind sehr schwer zu finden.
ich koennte mit einer gegenteiligen pauschalbehauptung kommen. wenn die welt so simpel waere, gebe es sicherlich keine exploits fuer sprachen mit VM+GC.

Bietchiebatchie
2007-10-16, 16:28:24
nur wenn du arrays verbietest, ansonsten kannst du immer einen overflow haben, wenn auch nur im scope vom array.

wenn nun beim Zugriff auf das Array immer der Index geprüft wird ist - was die CLR macht - ist ein Bufferoverflow absolut unmöglich. (Das eine Exception geworfen wird, falls der Index ungültig ist, ist eine vollkommen andere Geschichte.)


solange du auf objekte referenzierst, hilft dir eine VM nicht dieses leak zu finden. ich hab schon serverapplikationen gesehen (java) die alle 24h neu gestartet wurden wegen solcher leaks.
Ja, natürlich ist es möglich Applikationen zu schreiben, bei denen dir irgendwann der Speicher ausgeht. Dies ist aber nur dann der Fall, wenn die Applicationen vorgibt diesen Speicher auch zu brauchen; in der Regel weil irgendwelche Referenzen explizit im Speicher gehalten werden.
Das ist aber was vollkommen anderes als "klassische" Memory-Leaks bei denen man einfach vergisst bestimmten Speicher wieder freizugeben.

Bietchiebatchie
2007-10-16, 16:37:58
auch dann, ist das moeglich.

stell dir nur vor du hast ein array von textureresourcen und jemand ist so smart speicher zu sparen indem er sich nur eine 16bit ID drauf speichert (also den index). dann loescht das system die texture (wesehalb auch immer), somit hast du nun einen wilden pointer (damit mein ich nicht den vom array auf das objekt, denn der ist nun auf null, sondern die ID). allokierst du nun ein neues objekt an die selbe stelle im array (z.b. animierte textur die von texture abgeleitet war) ist der pointer weiterhin "wild" und arbeitet nun ploetzlich auf nem voellig falschen objekt.

edit: alternativ kann ich dir natuerlich auch einen uninitialisierten index bieten ;)

Was soll denn der Sinn von diesem Vorgehen sein? Statt direkt die Referenz zu speichern (32Bit) speichert man eine 16bit ID und muss dafür 2 mal dereferenzieren bevor man das Objekt hat, super Optimierung ;)

Natürlich, das Beispiel ist gut - um zu zeigen dass man natürlich in jedem System Müll bauen will, wenn man unbedingt darauf besteht.

Ich stimme übrigens Demirug: das ganze ist kein "wild pointer", "wild index" von mir aus.

micki
2007-10-16, 16:42:47
wenn nun beim Zugriff auf das Array immer der Index geprüft wird ist - was die CLR macht - ist ein Bufferoverflow absolut unmöglich. (Das eine Exception geworfen wird, falls der Index ungültig ist, ist eine vollkommen andere Geschichte.)und dann kommt jemand auf die idee, er koennte in einem array von 0 bis 255 ein array fuer den namen eines users haben und an position 256 ein flag ob es ein admin ist oder nicht.
dann kommt ein lustiger 'exploiter' der 256 zeichen fuer seinen namen angibt und schon hat er mittels bufferoverflow admin-rechte.

nein, sag mir nicht wie unsinnig das ist es so zu machen. es ist moeglich.


Ja, natürlich ist es möglich Applikationen zu schreiben, bei denen dir irgendwann der Speicher ausgeht. Dies ist aber nur dann der Fall, wenn die Applicationen vorgibt diesen Speicher auch zu brauchen; in der Regel weil irgendwelche Referenzen explizit im Speicher gehalten werden. Das ist aber was vollkommen anderes als "klassische" Memory-Leaks bei denen man einfach vergisst bestimmten Speicher wieder freizugeben.
der einzige unterschied ist nur, dass du bei impliziter freigabe nicht aus versehen etwas freigeben kannst, worauf ein pointer referenziert. es schuetzt dich aber nicht, dass deine applikation ein memoryleak hat.
ob klassisch weil man vergisst explizit delete aufzurufen, oder neumodern, weil man vergisst irgendwo nen zeiger du deferenzieren.

Demirug
2007-10-16, 16:48:33
also nicht ein undefiniert in der welt indizierender wert?

Bei einem „wild pointer“ verweist der Pointer auf eine Speicherstelle an der kein Objekt von dem Type des Pointers liegt. Im besten Fall ist es eine ungültige Speicherstelle und man bekommt sofort eine Access Violation. Im schlimmsten Fall schreibt man damit wild im Speicher herum und dann passieren ganz komische Dinge. An sowas kann man sehr lange suchen.


ich koennte mit einer gegenteiligen pauschalbehauptung kommen. wenn die welt so simpel waere, gebe es sicherlich keine exploits fuer sprachen mit VM+GC.

Das ist keine Pauschalbehauptung sonder Erfahrungswerte. In der Regel wird dabei aber die VM/GC angegriffen und die sind ja häufig mit C++ programmiert.

micki
2007-10-16, 17:06:07
Bei einem „wild pointer“ verweist der Pointer auf eine Speicherstelle an der kein Objekt von dem Type des Pointers liegt.das hast du dir gerade selbst dahindefiniert, ansonsten gebe es keine wildpointer auf byte, weil der ganze speicher aus bytes besteht (siehe assembler, jeder ptr ist nur ein byte-offset).
bleiben wir doch einfach bei einer addressierung auf einen nicht vorgesehenen speicherbereich.



Im besten Fall ist es eine ungültige Speicherstelle und man bekommt sofort eine Access Violation. Im schlimmsten Fall schreibt man damit wild im Speicher herum und dann passieren ganz komische Dinge. An sowas kann man sehr lange suchen. jup, ne outofbound exception ist da sehr net. schlimm ist wenn man ewig sucht, weil alle jahre lang ploetzlich irgend ein effect ne falsche textur zugewiesen bekommt ohne dass etwas abstuerzt. ne qual.




Das ist keine Pauschalbehauptung sonder Erfahrungswerte. In der Regel wird dabei aber die VM/GC angegriffen und die sind ja häufig mit C++ programmiert.
'in der regel' heisst aber nicht 'solche fehler lassen sich leicht finden'. es gibt dann auch die 'bitches' die man naechtelang sucht. und genau das kann es auch bei sprachen mit VM+GC geben solange du indizieren kannst. durch den dauernden boundscheck findest du das nur oefter. aber eben nicht immer.

Bietchiebatchie
2007-10-16, 17:25:23
und dann kommt jemand auf die idee, er koennte in einem array von 0 bis 255 ein array fuer den namen eines users haben und an position 256 ein flag ob es ein admin ist oder nicht.
dann kommt ein lustiger 'exploiter' der 256 zeichen fuer seinen namen angibt und schon hat er mittels bufferoverflow admin-rechte.

nein, sag mir nicht wie unsinnig das ist es so zu machen. es ist moeglich.


Ja ok, wenn du behauptest, dass man auch unter einer VM Scheiße bauen kann geb ich dir ja recht; aber gilt für jede Programmiersprache und wird auch immer so bleiben.
Selbst in sql kann ich den Karren an die Wand fahren, wenn ich nur genug full-table joins mache. Das ändert aber letztlich nix daran, dass sql ziemlich idiotensicher ist.

Das Problem das ich habe ist, dass man in deine Aussagen sowas wie "VMs sind unnötig, da man auch da Memory-Probleme bekommen kann" interpretieren kann. Das ist in meinen Augen absolut falsch da eben ein fundamtenaler Unterschied zwischen
"Ich fahre den Wagen absichtlich mit 250 gegen die Wand" (man fodert den Computer explizit an Schrott zu bauen)
und
"Der Wagen explodiert beim Aussteigen, nur weil ich vergessen habe, den Zündschlüssel zu ziehen" (delete vergessen)

Desweiteren hatte ich außerdem schon mal ein echtes .net memory Problem http://www.forum-3dcenter.org/vbulletin/showthread.php?t=355137 . Die Lösung des ganzen war übrigens überaus simpel: Die CLR brauch u.U. Ewigkeiten (> 2h) um sich auf einen konstanten Ramverbrauch einzupendeln.

Demirug
2007-10-16, 17:31:08
Natürlich kann es wild pointer auf Bytes geben. Alleine schon deswegen weil ein Pointer eben auch auf ungültige Speicherbereiche verweisen kann. Zudem sprechen wir hier doch von höheren Programmiersprachen und da besteht der Speicher eben nicht nur aus Bytes. Pointer type casts sind zudem ja ein Teil des Übels.

Ich will ja gar nicht abstreite das man sich in einer VM/CG Umgebung immer noch in den Fuß schießen kann. Allerdings ist es wesentlich schwerer und ich hatte bis heute keine undefinierten plötzlichen Absturz mit C#. In C++ passiert sowas häufiger. Ich bekomme das sehr gut mit weil solche Fehler immer bei mir laden weil man sie ja niemanden zuordnen kann.

micki
2007-10-16, 17:41:27
Das Problem das ich habe ist, dass man in deine Aussagen sowas wie "VMs sind unnötig, da man auch da Memory-Probleme bekommen kann" interpretieren kann. Das ist in meinen Augen absolut falsch da eben ein fundamtenaler Unterschied zwischen
"Ich fahre den Wagen absichtlich mit 250 gegen die Wand" (man fodert den Computer explizit an Schrott zu bauen)
und
"Der Wagen explodiert beim Aussteigen, nur weil ich vergessen habe, den Zündschlüssel zu ziehen" (delete vergessen)
das ist deine ansicht, meiner ansicht nach kann man mit soetwas viel schlimmere untugenden treiben und erfaehrt es nur nicht wirklich. das ist genau so wie beim threadstarter mit der performance, er faehrt die performancekarre vor die wand und weiss es nichtmal. erst wenn er zwei sprachen vergleicht, sieht er das.
wenn leute jedoch rein auf VM+GC setzen, woher wollen sie dann ueberhaupt wissen was sie anstellen?
viele glauben blauaeugig und unabrueckbar an behauptungen wie "Ist eh schneller weil GC enthalten ist" oder "kann keine momeryleaks geben" oder "kann keine bufferoverflows haben" und genau das ist das problem. nicht die sprachen, sondern der aberglaube drumherum.
wie ich hier schonmal sagte, nutze ich sowohl assembler als auch lua um ans ziel zu kommen und wenn mir jemand sagt, dass lua viel langsammer als assembler ist, lach ich den aus.
andere sollten vielleicht auch mal ueber den tellerrand schauen.

Desweiteren hatte ich außerdem schon mal ein echtes .net memory Problem http://www.forum-3dcenter.org/vbulletin/showthread.php?t=355137 . Die Lösung des ganzen war übrigens überaus simpel: Die CLR brauch u.U. Ewigkeiten (> 2h) um sich auf einen konstanten Ramverbrauch einzupendeln.
wenn man es nicht am eigenen arsch erfaehrt, wuerde man sowas ja auch nur als bloeden flame aufwassen, netwahr? :D

micki
2007-10-16, 17:50:20
Natürlich kann es wild pointer auf Bytes geben. Alleine schon deswegen weil ein Pointer eben auch auf ungültige Speicherbereiche verweisen kann. Zudem sprechen wir hier doch von höheren Programmiersprachen und da besteht der Speicher eben nicht nur aus Bytes. Pointer type casts sind zudem ja ein Teil des Übels.

Ich will ja gar nicht abstreite das man sich in einer VM/CG Umgebung immer noch in den Fuß schießen kann. Allerdings ist es wesentlich schwerer und ich hatte bis heute keine undefinierten plötzlichen Absturz mit C#. In C++ passiert sowas häufiger. Ich bekomme das sehr gut mit weil solche Fehler immer bei mir laden weil man sie ja niemanden zuordnen kann.
sowas kenn ich :D
da betet man dann jedes toll an was einem ein wenig hilft:), nur wuerde ich es eben auch so bei C#/Java sehen, da laeuft das tool immer mit. bei c++ muss man sich das manuel dazulinken (gibt ja genug zur auswahl http://en.wikipedia.org/wiki/Memory_debugger). aber deswegen sehe ich die sprache nicht als sicherer an. sie piekt dich nur eher beim arbeiten damit auf die nase wenn du scheisse baust. wenn bei nem kunden ne null-ptr-exception fliegt oder ne normale OS-exception, gibt dann keinen unterschied. oder ueberseh ich da was? (sag nicht stacktrace, den hat seit 5jahren wohl jede c++ app auch die was von sich haelt:D)

java und c# haben dafuer andere design flaws die c++ nie zulaesst und die ewige kopfzerbrechen machen koennen.

Grestorn
2007-10-16, 18:22:24
java und c# haben dafuer andere design flaws die c++ nie zulaesst und die ewige kopfzerbrechen machen koennen.

Die da wären?

micki
2007-10-16, 18:33:21
Die da wären?
bewust nicht gesagt, sonst gibt es hier noch mehr auseinandersetzungen. wir haben ja schon performance und sicherheit durch, das reicht mir.
wenn du beide sprachen gut kennst, kennst du sicherlich selbst die weakpoints.

Grestorn
2007-10-16, 18:45:54
bewust nicht gesagt, sonst gibt es hier noch mehr auseinandersetzungen. wir haben ja schon performance und sicherheit durch, das reicht mir.
wenn du beide sprachen gut kennst, kennst du sicherlich selbst die weakpoints.

Es gibt sicherlich Schwächen, ich kenne einige. Aber keine dieser Schwächen würde ich als Nachteil ggü. C++ sehen.

Für C++ sprechen nur Randbedingungen, die aber nicht die Sprache selbst betreffen. Z.B. die weitgehende Unabhängigkeit von installierten Komponenten (JVM, .NET).

Als Sprache sehe ich kaum keinen Vorteil von C++. Nicht mal die Möglichkeit, manuell Speicher zu verwalten, ist für die allermeisten Anwendungsfälle in irgendeiner Weise von Vorteil.

Trap
2007-10-16, 23:04:51
Als Sprache sehe ich kaum keinen Vorteil von C++.
C++ hat eine turingvollständige Subsprache zur Codegeneration. Allerdings war das wohl mehr ein Unfall bei der Sprachentwicklung und ist ziemlich hässlich zu benutzen.

Gast
2007-10-17, 09:03:44
Es gibt sicherlich Schwächen, ich kenne einige. Aber keine dieser Schwächen würde ich als Nachteil ggü. C++ sehen.

Für C++ sprechen nur Randbedingungen, die aber nicht die Sprache selbst betreffen. Z.B. die weitgehende Unabhängigkeit von installierten Komponenten (JVM, .NET).

Als Sprache sehe ich kaum keinen Vorteil von C++. Nicht mal die Möglichkeit, manuell Speicher zu verwalten, ist für die allermeisten Anwendungsfälle in irgendeiner Weise von Vorteil.
Damit sagst du nur aus, dass du dich mit mit C#/Java auskennst, aber wohl nicht mit C++.

Grestorn
2007-10-17, 09:12:51
Damit sagst du nur aus, dass du dich mit mit C#/Java auskennst, aber wohl nicht mit C++.

Rofl.

Sag doch mal, wo C++ Sprachvorteile hat. Ich lasse mich ja gerne überzeugen.

Jedenfalls geht mir in Java/C# nichts ab, was ich in C++ gerne genutzt habe. Umgekehrt fallen mir gleich eine ganze Reihe von netten Dingen ein.

Das Argument von Trap (die Textersetzungs/Makrosprache via Preprozessor) halte ich nicht für einen Vorteil von C++. Auch wenn es da sicher andere Meinungen gibt, aber für mich ist die Folge des Einsatzes von Makros nur ein deutlich schwerer nachzuvollziehender Code.

Xmas
2007-10-17, 09:39:05
Das Argument von Trap (die Textersetzungs/Makrosprache via Preprozessor) halte ich nicht für einen Vorteil von C++. Auch wenn es da sicher andere Meinungen gibt, aber für mich ist die Folge des Einsatzes von Makros nur ein deutlich schwerer nachzuvollziehender Code.
Trap meint wohl eher Template Metaprogramming. Das ist allerdings auch meist unlesbar.

Grestorn
2007-10-17, 10:17:49
Trap meint wohl eher Template Metaprogramming. Das ist allerdings auch meist unlesbar.

Hm. Ich glaube nicht, dass er das meinte. Und wenn doch: Das, was man durch Templates erreicht, kann man sowohl in Java als auch in C# durch bessere Mittel erreichen (Generics)

Trap
2007-10-17, 10:28:40
Das Argument von Trap (die Textersetzungs/Makrosprache via Preprozessor) halte ich nicht für einen Vorteil von C++.
Makros sind nicht turingvollständig.
Hm. Ich glaube nicht, dass er das meinte. Und wenn doch: Das, was man durch Templates erreicht, kann man sowohl in Java als auch in C# durch bessere Mittel erreichen (Generics)
Generics ersetzen Template Metaprogramming bei weitem nicht, guck dir z.B. mal http://boost.org/libs/spirit/index.html oder http://boost.org/libs/static_assert/static_assert.htm an.

Allerdings ist template metaprogramming in C++ ein hässlicher Hack, es gibt auch Sprachen die sowas deutlich sauberer integriert haben.

Grestorn
2007-10-17, 10:45:07
Generics ersetzen Template Metaprogramming bei weitem nicht, guck dir z.B. mal http://boost.org/libs/spirit/index.html oder http://boost.org/libs/static_assert/static_assert.htm an.

Wenn Du nochmal genau liest, wirst Du feststellen, dass ich das auch nicht behauptet habe.

Na gut, vielleicht nicht so ausgedrückt, wie ich es wollte. Ich hätte schreiben sollen: "Das was man üblicherweise mit Templates erreichen will..."

Gast
2007-10-17, 11:01:26
Allerdings ist template metaprogramming in C++ ein hässlicher Hack, es gibt auch Sprachen die sowas deutlich sauberer integriert haben.Welche denn?

Trap
2007-10-17, 11:03:35
Welche denn?
Lisp in allen Varianten.

micki
2007-10-17, 11:26:06
Rofl.

Sag doch mal, wo C++ Sprachvorteile hat. Ich lasse mich ja gerne überzeugen.
Du kannst in c++ nicht aus versehen vom c-tor aus auf elemente zugreifen die erst von dem c-tor einer abgeleiteten klasse initialisiert werden. in C# ist das des oefteren der grund fuer lange debugging sessions. (oder wurde das in C# inzwischen ausgemerzt?)

micki
2007-10-17, 11:27:41
Na gut, vielleicht nicht so ausgedrückt, wie ich es wollte. Ich hätte schreiben sollen: "Das was man üblicherweise mit Templates erreichen will..."
viele dinge die generics nicht bieten sind etwas was man normalerweise mit templates erreichen will.


Jedenfalls geht mir in Java/C# nichts ab, was ich in C++ gerne genutzt habe.
"Es ist schwer etwas zu vermissen was man garnicht kennt" ;D

Demirug
2007-10-17, 11:34:41
Du kannst in c++ nicht aus versehen vom c-tor aus auf elemente zugreifen die erst von dem c-tor einer abgeleiteten klasse initialisiert werden. in C# ist das des oefteren der grund fuer lange debugging sessions. (oder wurde das in C# inzwischen ausgemerzt?)

Mir ist nicht ganz klar was du damit meinst. Beim cTor einer Klasse sind die Elemente der abgeleiteten Klassen doch überhaupt nicht im scope.

micki
2007-10-17, 11:38:16
Mir ist nicht ganz klar was du damit meinst. Beim cTor einer Klasse sind die Elemente der abgeleiteten Klassen doch überhaupt nicht im scope.
virtual function anyone? ;)

Coda
2007-10-17, 11:54:28
Es gibt virtuelle Konstruktoren in C#? :|

Hm. Ich glaube nicht, dass er das meinte. Und wenn doch: Das, was man durch Templates erreicht, kann man sowohl in Java als auch in C# durch bessere Mittel erreichen (Generics)
Doch tut er. Und nein das lässt sich nicht durch Generics ersetzen. Templates sind viel viel mächtiger.

Es gibt für C++ sogar Parsergeneratoren die die Generation des für den Parser nötigen Code zur Compile-Zeit machen (Boost::Spirit).

micki
2007-10-17, 12:06:15
Es gibt virtuelle Konstruktoren in C#? :|\virtual function anyone? ;)
du trollst mich doch nicht gerade, oder? :p

Coda
2007-10-17, 12:08:46
Nein, ihr hattet es gerade von Konstruktoren. Ich versteh nicht wie du darauf kommst, dass in C# die Members von abgeleiteten Klassen im cTor im Scope sind?!?

micki
2007-10-17, 12:13:28
Nein, ihr hattet es gerade von Konstruktoren. Ich versteh nicht wie du darauf kommst, dass in C# die Members von abgeleiteten Klassen im cTor im Scope sind?!?
du weisst also nicht dass man ueber eine 'virtual function' in C#/java auf die member der abgeleiteten klassen zugreifen kann, vom ctor der root-klasse?

Coda
2007-10-17, 12:18:58
Sagen wir so: Ich bin bisher nicht auf die Idee gekommen sowas zu konstruieren. Wie reagiert C++ denn in dem Fall?

Demirug
2007-10-17, 12:43:32
Sagen wir so: Ich bin bisher nicht auf die Idee gekommen sowas zu konstruieren. Wie reagiert C++ denn in dem Fall?

C++ führt in solchen Fällen die virtuelle Funktion aus die zu der Klasse gehört in deren ctor du gerade bist. C# dagegen führt die virtuelle Funktion der Klasse aus die du gerade erzeugst. Hat beides seine Vor und Nachteile. Allgemein kann man sagen das aufrufen von virtuellen Funktionen im ctor ist immer etwas evil.

micki
2007-10-17, 12:46:19
Allgemein kann man sagen das aufrufen von virtuellen Funktionen im ctor ist immer etwas evil.
im falle von c++ ist es nicht evil. du kannst sie wie jede andere normale funktion aufrufen, ohne dass sie querschiesst weil jemand mal von deiner klasse ableitet.

Gast
2007-10-17, 12:51:06
Allerdings ist template metaprogramming in C++ ein hässlicher Hack, es gibt auch Sprachen die sowas deutlich sauberer integriert haben.

Template Metaprogramming erweitert C++ um Funktionale Programmierung. Es ist auch nicht unsauber oder ein hässlicher Hack. Wenn es gut eingesetzt wird ist es verdammt elegant.
Die meisten Programmiern sind einfach unfähig richtig damit umzugehen.



Na gut, vielleicht nicht so ausgedrückt, wie ich es wollte. Ich hätte schreiben sollen: "Das was man üblicherweise mit Templates erreichen will..."
Das was DU überlichweise erreichen willst.
Imo ist ein gekonnter Umgang mit Metaprogramming eine der Grundvoraussetzungen um jemanden als sehr guten Programmierer bezeichnen zu können.

Grestorn
2007-10-17, 12:56:15
Du kannst in c++ nicht aus versehen vom c-tor aus auf elemente zugreifen die erst von dem c-tor einer abgeleiteten klasse initialisiert werden. in C# ist das des oefteren der grund fuer lange debugging sessions. (oder wurde das in C# inzwischen ausgemerzt?)

Das klappt auch in Java recht schön mit all den zugehörigen netten Nebeneffekten.

Ohne Zweifel ein Mangel, auch wenn man keine Stunden brauchen sollte, das Problem zu finden. Im Gegensatz zu Wild Pointern und Speicherlecks ist so etwas im Debugger ja sofort sichtbar.

Grestorn
2007-10-17, 12:56:52
Das was DU überlichweise erreichen willst.
Imo ist ein gekonnter Umgang mit Metaprogramming eine der Grundvoraussetzungen um jemanden als sehr guten Programmierer bezeichnen zu können.

Jaja, scho recht :rolleyes:

Es gibt nichts was man nur durch Templates, nicht aber durch ein intelligentes OO-Design erreichen kann. Auch Generics verschönern den Code nur und verbessern die Typsicherheit, notwendig für "sehr gute" Programmierung sind sie keineswegs.

micki
2007-10-17, 12:57:49
Ohne Zweifel ein Mangel, auch wenn man keine Stunden brauchen sollte, das Problem zu finden. Im Gegensatz zu Wild Pointern und Speicherlecks ist so etwas im Debugger ja sofort sichtbar.
da behaupte ich auch pauschal das gegenteil.

Grestorn
2007-10-17, 13:01:08
da behaupte ich auch pauschal das gegenteil.

Tja. Was soll man sagen. Dass ein Member zu spät intialisiert wird, sehe ich sofort und nachvollziehbar im Debugger.

Wild Pointer und Speicherlecks kann ich beide nicht zuverlässig erkennen, da sie fieser Weise oft erst nach Stunden und nicht immer reproduzierbar auftreten.

Selbst wenn man entsprechende Werkzeuge einsetzt, ist die Suche oft ein Problem, an dem viele letztlich scheitern.

Grestorn
2007-10-17, 13:02:50
viele dinge die generics nicht bieten sind etwas was man normalerweise mit templates erreichen will.

Beispiel?

Und wie kommst Du darauf, dass ich Template bzw. C++ nicht kenne? Ich wusste gar nicht, dass Du so genau über mein Profil und meine Projekterfahrung bescheid weisst...

Gast
2007-10-17, 13:05:28
Bin zwar grundsätzlich gleich Meinung, aber Speicherlecks können auch unter C++ recht zuverlässig gefunden/ermittelt werden können. Und wenn VS da gleich schon Qualitäten hätte und man keine externen Tools bräuchte, wäre dies mit Sicherheit auch seltener... :)

Grestorn
2007-10-17, 13:05:30
im falle von c++ ist es nicht evil. du kannst sie wie jede andere normale funktion aufrufen, ohne dass sie querschiesst weil jemand mal von deiner klasse ableitet.

Oh, es ist aber etwas, das unerfahrene Programmierer überrascht ("wieso wird nicht die überschriebene Methode gerufen?")

Genauso, wie es den unerfahrenen Java-Programmierer überrascht, dass die Membervariablen über den Initializer initialisiert werden, nachdem eine virtuelle Methode ggf. schon darauf zugegriffen hat.

Gast
2007-10-17, 13:05:50
Es gibt nichts was man nur durch Templates, nicht aber durch ein intelligentes OO-Design erreichen kann. Auch Generics verschönern den Code nur und verbessern die Typsicherheit, notwendig für "sehr gute" Programmierung sind sie keineswegs.
Es gibt in dem Sinne nichts was man nicht mit einer turingvollständigen Sprache nicht machen kann. Ist Brainfuck nicht auch turingvollständig? :rolleyes:

Demirug
2007-10-17, 13:06:32
im falle von c++ ist es nicht evil. du kannst sie wie jede andere normale funktion aufrufen, ohne dass sie querschiesst weil jemand mal von deiner klasse ableitet.

Es ist evil weil es sich anders verhält als ein Aufruf einer virtuellen Funktion aus einer anderen Funktion der Klasse. Du kannst dir da relative leicht eine Stolperfalle bauen. IMHO sollte der Aufruf von virtuellen Funktionen im Konstruktor verboten werden bzw nur in Form eines expliziten Aufrufs erlaubt sein.

Und ja ich musste schon Bugs suchen die aufgrund dieses C++ Verhaltens entstanden sind. Mit C# hätte es in einigen Fällen funktioniert. Allerdings nicht in allen und deswegen bin ich eher für ein Verbot.

Grestorn
2007-10-17, 13:07:22
Bin zwar grundsätzlich gleich Meinung, aber Speicherlecks können auch unter C++ recht zuverlässig gefunden/ermittelt werden können. Und wenn VS da gleich schon Qualitäten hätte und man keine externen Tools bräuchte, wäre dies mit Sicherheit auch seltener... :)

Die Existenz von Speicherlecks lässt sich mit den entsprechenden Tools leicht nachweisen. Die Ursache nicht immer so leicht.

Grestorn
2007-10-17, 13:08:30
Es gibt in dem Sinne nichts was man nicht mit einer turingvollständigen Sprache nicht machen kann. Ist Brainfuck nicht auch turingvollständig? :rolleyes:

Wozu brauche ich Templates ZUSÄTZLICH zur eigentlichen Programmiersprache (abgesehen von Typsicherheit und der Vermeidung von Downcasts)?

Demirug
2007-10-17, 13:13:01
Bin zwar grundsätzlich gleich Meinung, aber Speicherlecks können auch unter C++ recht zuverlässig gefunden/ermittelt werden können. Und wenn VS da gleich schon Qualitäten hätte und man keine externen Tools bräuchte, wäre dies mit Sicherheit auch seltener... :)

Speicherlecks sind doch die harmlosesten Heap Fehler und die zeigt die debug runtime der msvcrt sogar an. Zwar leider nur mit der Allokations id aber häufig reicht das sogar schon. Ich hätte aber auch nichts dagegen wenn sie da noch bessere Tools gleich einbauen würden.

Gast
2007-10-17, 13:13:32
Wozu brauche ich Templates ZUSÄTZLICH zur eigentlichen Programmiersprache (abgesehen von Typsicherheit und der Vermeidung von Downcasts)?
:lol:

Ich empfehle zur Lektüre "C++ Templates - The complete Guide".
Für die Grundlagen und die Denkweise zu verstehen imo das beste Buch.

Ansonsten ist es auch nicht verkehrt sich die Vorteile funktionaler Programmiersprachen anzuschauen.

Gast
2007-10-17, 13:16:37
Die Existenz von Speicherlecks lässt sich mit den entsprechenden Tools leicht nachweisen. Die Ursache nicht immer so leicht.Deswegen schrub ich ja dies auch kursiv :)

Grestorn
2007-10-17, 13:20:01
:lol:

Ich empfehle zur Lektüre "C++ Templates - The complete Guide".
Für die Grundlagen und die Denkweise zu verstehen imo das beste Buch.

Ansonsten ist es auch nicht verkehrt sich die Vorteile funktionaler Programmiersprachen anzuschauen.

Nenn mich altmodisch... aber selbst nach den entsprechenden Vorlesungen damals habe ich den Nutzen von funktionaler Programmierung in der Praxis nicht eingesehen. Und ich bin da scheinbar nicht alleine.

Sollen sich die Theoretiker daran erfreuen. Bei der Lösung von realen Problemen komme ich ganz gut ohne FP aus.

Gast
2007-10-17, 13:41:00
Nenn mich altmodisch...
Warum sollte ich?
Jeder soll für sich selbst entscheiden was er lernen will.
Man kommt gut ohne aus. Man kann, wenn mans richtig einsetzt, die Reliability, Performance und Usability damit verbessern.
Falsch eingesetzt bewirkt es genau das Gegenteil...

Gast
2007-10-17, 14:26:28
Tja. Was soll man sagen. Dass ein Member zu spät intialisiert wird, sehe ich sofort und nachvollziehbar im Debugger. tja, was soll ich sagen, debuggen ist nicht das ansehen von fehlern im debugger, sondern das suchen solch einen fehlers, nicht initialisierte variablen sind da das simpelste. komplexer wird es wenn die funktionen ganz anderes verhalten heraufbeschwoeren. da ist ein memleak einfacher zu finden


Wild Pointer
wir haben schon gestern geklaert, solange du addressieren kannst, kannst du wild pointer haben (array+offset ist auch addressieren).


Speicherlecks kann ich beide nicht zuverlässig erkennen, da sie fieser Weise oft erst nach Stunden und nicht immer reproduzierbar auftreten. jup, kenn ich, deswegen hatte ich ja von dem beispiel erzaehlt, dass eine java-server-app alle 24h wegen nem memleak neugestartet wurde.

micki
2007-10-17, 14:28:36
Alt 17.10.2007, 14:26:28
das war ich, sorry, das cookie war weg nach dem lunch.

Grestorn
2007-10-17, 15:43:51
tja, was soll ich sagen, debuggen ist nicht das ansehen von fehlern im debugger, sondern das suchen solch einen fehlers, nicht initialisierte variablen sind da das simpelste. komplexer wird es wenn die funktionen ganz anderes verhalten heraufbeschwoeren. da ist ein memleak einfacher zu finden

Nö, ganz sicher nicht. Wenn sich mein Programm nachvollziehbar falsch verhält, ist es nicht so sonderlich schwer einzugrenzen, wo das Fehlverhalten passiert. Da das Verhalten in diesem Szenario genau definiert ist, ist es auch deterministisch und nicht zufällig.

Das ist bei Speicherlecks und WildPointers ganz anders.

wir haben schon gestern geklaert, solange du addressieren kannst, kannst du wild pointer haben (array+offset ist auch addressieren).
Im schlimmsten Falle komme ich dann aber auf eine null-Referenz (Exception) oder ein falsches Objekt.

Klassische Wild-Pointer, also dass man ein bereits freigegebenes Objekt referenziert, kann nicht passieren.

Und die netten Effekte, wenn man auf einem auf dem Stack allokierten Objekt einen Überlauf hat, dadurch Nachbarvariablen oder gar den Return-Pointer überschreibt und dadurch die absolut tollsten Ergebnisse (natürllich nicht reproduzierbar) hat, sind auch völlig ausgeschlossen.

jup, kenn ich, deswegen hatte ich ja von dem beispiel erzaehlt, dass eine java-server-app alle 24h wegen nem memleak neugestartet wurde.

Natürlich kann man auch in Java ein Speicherleck produzieren. Dazu muss man sich aber richtig anstrengen und einen Fehler im Alorithmus haben. Eigentlich kann das nur durch immer weiter wachsende Datenstrukturen passieren, und das lässt sich viel leichter vermeiden als ein vergessenes delete.

micki
2007-10-17, 16:03:07
Nö, ganz sicher nicht. Wenn sich mein Programm nachvollziehbar falsch verhält, ist es nicht so sonderlich schwer einzugrenzen, wo das Fehlverhalten passiert.klar, alles nachvollziehbare kann man.. emm.. nicht sonderlich schwer nachvollziehen.

Da das Verhalten in diesem Szenario genau definiert ist, ist es auch deterministisch und nicht zufällig. aus der sicht, da PCs deterministisch sind, ist jeder bug leicht zu tracken. auch so ein memoryleak in einer java-server-app wegen vielleicht solch einen funktions-ueberladen und aufruf aus dem c-tor;

Das ist bei Speicherlecks und WildPointers ganz anders.
seh ich weiterhin ganz anders.


Im schlimmsten Falle komme ich dann aber auf eine null-Referenz (Exception) oder ein falsches Objekt. jup, bzw accessviolation bzw falscher speicher.


Klassische Wild-Pointer, also dass man ein bereits freigegebenes Objekt referenziert, kann nicht passieren. du hast gestern echt nicht mitgelesen, also nochmals das beispiel:
du merkst dir den index auf ein objekt im array. gibst das objet im array frei, legst ein neues an und arbeitest dann 'wild' auf einem ganz anderen objekt.

Grestorn
2007-10-17, 16:23:28
du hast gestern echt nicht mitgelesen, also nochmals das beispiel:
du merkst dir den index auf ein objekt im array. gibst das objet im array frei, legst ein neues an und arbeitest dann 'wild' auf einem ganz anderen objekt.

Klar kann das passieren, aber einen solchen Fehler muss man in Java fast schon erzwingen. Wogegen in C++ ein fehlendes delete reicht.

Dass man versehentlich auf ein falsches Objekt verweist ist sowieso eher ungewöhnlich.

Meist verweist man doch auf gar kein gültiges Objekt mehr. Im besten Falle zeigt der Pointer ganz aus dem Prozesskontext raus -> Access Violation und damit Crash. Oder, was noch viel schlimmer ist, er zeigt Mitten auf den Heap der Applikation (kein Crash!) auf irgendeine Stelle irgendeines anderes Objekts, was man sich dann total zerschreibt.

Diese beiden Fehler können in Java/.NET nicht passieren und sind mit Abstand die am schwersten zu findenden.

Coda
2007-10-17, 17:17:45
Beispiel?
Boost::Spirit. Metaprogrammierung ganz allgemein. Und ja, das ist nützlich.

micki
2007-10-17, 17:18:32
Klar kann das passieren, aber einen solchen Fehler muss man in Java fast schon erzwingen. Wogegen in C++ ein fehlendes delete reicht. es geht nicht darum wann etwas entsteht, nur dass die sprache es nicht ausschliesst wie soviele pauschal behaupten (du zuerst ja auch).

Dass man versehentlich auf ein falsches Objekt verweist ist sowieso eher ungewöhnlichgenau das macht ein wildpointer.

Meist verweist man doch auf gar kein gültiges Objekt mehr. Im besten Falle zeigt der Pointer ganz aus dem Prozesskontext raus -> Access Violation und damit Crash. Oder, was noch viel schlimmer ist, er zeigt Mitten auf den Heap der Applikation (kein Crash!) auf irgendeine Stelle irgendeines anderes Objekts, was man sich dann total zerschreibt. der vorteil von java ist dass das objekt noch exisitert, vielleicht sogar ewig existieren wird. du hast also nur ein memory-leak statt einem wild-ptr. und wie du oben schon gesagt hattest, sind memory-leaks nicht immer einfach zu finden. (nichtmal der beweis ob es ein memory leak ist ist trivial).

Diese beiden Fehler können in Java/.NET nicht passieren und sind mit Abstand die am schwersten zu findenden.
wie gesagt, ein ptr ist wildes indizieren. solange du das kannst, hast du diese schwer zu trackenden fehler. der einzige unterschied ist das resultat solch eines fehlers. bei wilden ptr in den heap, hast du irgendwann, irgendwie ein crash... vielleicht. bei wildem indizieren in deinen arrays hast du die fehler innerhalb dieses scopes. aber es sind die selben fehler und koennen genau so schwer zu finden sein (ich spreche aus trauriger erfahrung).

Grestorn
2007-10-17, 18:28:52
der vorteil von java ist dass das objekt noch exisitert, vielleicht sogar ewig existieren wird. du hast also nur ein memory-leak statt einem wild-ptr. und wie du oben schon gesagt hattest, sind memory-leaks nicht immer einfach zu finden. (nichtmal der beweis ob es ein memory leak ist ist trivial).

Sorry, aber das ist Quark.

Ein Speicherleck bedeutet, dass während des Programmlaufs immer mehr Speicher verbraucht wird. Ständig unnütz verbrauchter Speicher - wegen einmalig angelegter Objekte, die zwar referenziert aber eigentlich nicht mehr gebraucht werden - zählen nicht als Speicherleck.

D.h. irgendeine Struktur (Liste, Map, etc.) muss wachsen. Wenn lediglich Referenzen wiederverwendet werden und dabei auf neue Instanzen verwiesen wird, z.B. in einer Iteration oder beim wiederholten Aufruf einer bestimmten Funktion, kann es mit einem GC kein Speicherleck geben.

Aber ich denke, wir werden nicht zusammen kommen. Deswegen sollten wir das lassen.

Grestorn
2007-10-17, 18:30:29
Boost::Spirit. Metaprogrammierung ganz allgemein. Und ja, das ist nützlich.

Wirkt auf den ersten Blick auch sehr akademisch auf mich. Ohne Zweifel sehr interessant und auch elegant.

Aber für die tägliche Arbeit wohl eher nicht angebracht. Selbst wenn man einen Parser bauen will.

Coda
2007-10-17, 18:31:28
Aber für die tägliche Arbeit wohl eher nicht angebracht. Selbst wenn man einen Parser bauen will.
Blödsinn. Ich hab das schon zig mal produktiv verwendet und es ist für mich für kleinere Parser auf jeden Fall einfacher zu verwenden als Flex/Bison und mit weniger Ärger verbunden.

Hör auf auf der Ebene zu diskutieren, das ist lächerlich.

Grestorn
2007-10-17, 18:39:39
Blödsinn. Ich hab das schon zig mal produktiv verwendet und es ist für mich für kleinere Parser auf jeden Fall einfacher zu verwenden als Flex/Bison und mit weniger Ärger verbunden.

Hör auf auf der Ebene zu diskutieren, das ist lächerlich.

Hey, ich habe "wohl" geschrieben... Komm wieder runter. Ich kenne es zu wenig, um es wirklich einschätzen zu können. Schön, wenn es - zumindest für Dich - sinnvoll ist.

Coda
2007-10-17, 18:44:28
Das "zumindest für dich" kannst du dir auch sparen.

Grestorn
2007-10-17, 18:59:44
Das "zumindest für dich" kannst du dir auch sparen.

Naja, jedenfalls nicht für mich.

Was bist Du denn so biestig heute? Hab Dir doch nichts getan. Und lass mich gern eines besseren belehren.

del_4901
2007-10-17, 19:13:59
Und lass mich gern eines besseren belehren.

Das habe ich bei dir schon aufgegeben, und die Anderen hier, sind bestimmt auch nichtmehr weit davon entfernt.

micki
2007-10-17, 19:23:09
Sorry, aber das ist Quark.

Ein Speicherleck bedeutet, dass während des Programmlaufs immer mehr Speicher verbraucht wird. Ständig unnütz verbrauchter Speicher - wegen einmalig angelegter Objekte, die zwar referenziert aber eigentlich nicht mehr gebraucht werden - zählen nicht als Speicherleck. sorry, 1. ein speicherleck ist wenn speicher der freigegeben sein sollte es nicht ist (unabhaengig von der frequenz dessen).
2. niemand sagt dass es nur einen einzigen wildptr geben darf.


D.h. irgendeine Struktur (Liste, Map, etc.) muss wachsen. Wenn lediglich Referenzen wiederverwendet werden und dabei auf neue Instanzen verwiesen wird, z.B. in einer Iteration oder beim wiederholten Aufruf einer bestimmten Funktion, kann es mit einem GC kein Speicherleck geben.
stell dir vor, du willst das letzte element aus einer queue 'popen', dabei setzt du den end-ptr deiner queue-klasse auf das vorletzte element, lieferst dann das letzte zurueck. dabei hast du nun aber vergessen beim vorletzten element den next-ptr auf null zu setzen. schon hast du einen 'wild' ptr.
in c++ ruft jemand dann delete auf das objekt auf, da vielleicht nie auf "next" zugegriffen wird, wird dieser 'wild' ptr in c++ nie bemerkt werden (jedenfalls nicht durch laufzeit bugs), falls doch ist man natuerlich voll am arse.
in java ruft man natuerlich nicht 'delete' auf, man geht davon aus, dass das objekt einfach weg ist wenn man darauf nicht mehr referenziert. leider gottes gibt es ja in der queue ein element dessen next-ptr noch drauf zeigt. schon hast du dank "wildptr" ein memleak in java.

behaupte jetzt nicht, dass du das leicht herausfinden kannst. dafuer hab ich jetzt nichtmal genug informationen geliefert und das ist auch nicht der punkt ;)

micki
2007-10-17, 19:28:40
Naja, jedenfalls nicht für mich. da kann ich mich nur wiederholen, dass du ja nichts verimissen kannst, was du nicht kennst. templates sind taeglich eine sehr nuetzliche hilfe bei der programmierung, und das fuer optimierungen, fuer sicherheit, fuer 'arschabwischer'-funktionen, um die meiste funktionalitaet abzubilden (so wie man es moechte) die andere sprachen wie z.b. java als eingebauten funktionsumfang bieten (z.b. reflection) und diese auch nach spass zu erweitern (z.b. memory layout der reflektierten objekte im ram reflektieren).

und ich denke coder rastet nur aus weil du deine meinung mal wieder pauschal als tatsache darstellst ;)

Kabelsalat
2007-10-17, 20:28:24
Du kannst in c++ nicht aus versehen vom c-tor aus auf elemente zugreifen die erst von dem c-tor einer abgeleiteten klasse initialisiert werden. in C# ist das des oefteren der grund fuer lange debugging sessions. (oder wurde das in C# inzwischen ausgemerzt?)
du weisst also nicht dass man ueber eine 'virtual function' in C#/java auf die member der abgeleiteten klassen zugreifen kann, vom ctor der root-klasse?
im falle von c++ ist es nicht evil. du kannst sie wie jede andere normale funktion aufrufen, ohne dass sie querschiesst weil jemand mal von deiner klasse ableitet.
Das klappt auch in Java recht schön mit all den zugehörigen netten Nebeneffekten.

Ohne Zweifel ein Mangel, auch wenn man keine Stunden brauchen sollte, das Problem zu finden. Im Gegensatz zu Wild Pointern und Speicherlecks ist so etwas im Debugger ja sofort sichtbar.

Auch wenn ich die gesamte Diskussion als ziemlich kindisch empfinde, möchte ich hierzu Christopher Brumme aus dem Microsoft CLR-Team zitieren:


In nicht verwaltetem C++-Code wird die vtable während der Konstruktion aktualisiert, so dass ein Aufruf einer virtuellen Funktion zu diesem Zeitpunkt nur die Ebene der Objekthierarchie erreicht, die konstruiert wurde.

Meine Erfahrung besagt, dass genauso viele Programmierer vom C++-Verhalten irritiert sind, wie vom verwalteten Verhalten. Tatsache ist, dass viele Programmierer nicht über die Semantik virtueller Aufrufe während der Konstruktion und der Destruktion nachdenken, bevor sie einmal einen damit verknüpften Fehler suchen mussten.

Beide Verhaltensweisen sind für manche Programmierer geeignet, für andere nicht. Beide lassen sich logisch verteidigen. Für die CLR beruht die Entscheidung letztendlich auf unserem Wunsch, extrem schnelles Erstellen von Objekten zu unterstützen.

Grestorn
2007-10-17, 20:29:48
sorry, 1. ein speicherleck ist wenn speicher der freigegeben sein sollte es nicht ist (unabhaengig von der frequenz dessen).
2. niemand sagt dass es nur einen einzigen wildptr geben darf.

Das ist doch schlicht völlig falsch. Nach Deiner Definition hätte jedes Programm Speicherlecks.

Wenn der Speicherbedarf eines Programms nicht steigt (ohne das es einen Algorithmischen Grund dafür geht), dann hat es ein Speicherleck. Sonst nicht.

stell dir vor, du willst das letzte element aus einer queue 'popen', dabei setzt du den end-ptr deiner queue-klasse auf das vorletzte element, lieferst dann das letzte zurueck. dabei hast du nun aber vergessen beim vorletzten element den next-ptr auf null zu setzen. schon hast du einen 'wild' ptr.

Nein, ich habe einen Fehler in der Liste. Wenn ich über sie iteriere bekomme ich ein zusätzliches Element, das ich eigentlich dachte entfernt zu haben.

Es ist aber immer noch das Element, vollständig und intakt. Das heißt, ich kann darauf zugreifen, lesend und schreibend ohne Seiteneffekte. Und diesen Fehler zu debuggen ist sehr leicht: Jedesmal passiert genau das gleiche, keine Zufallseffekte wie bei echten C++ Wild Pointers.

Stell Dir vor, Du hättest in C++ zwar den Pointer deleted, aber vergessen ihn auf NULL zu setzen. Die Konsequenzen sind katastrophal und je nach dem wie die Objekte im Speicher verteilt sind, vollkommen zufällig!

maximAL
2007-10-17, 20:31:03
Template Metaprogramming erweitert C++ um Funktionale Programmierung.
hat beides rein gar nichts miteinander zu tun.

Coda
2007-10-17, 20:37:24
Naja die Metasprache die sich daraus ergibt ist schon funktional.

tokugawa
2007-10-17, 20:38:02
Es gibt zwei Varianten von Memory Leaks. Beide haben gemein, dass Speicher der nicht mehr sinnvoll genutzt wird weiter belegt ist (logisch - das ist die genaue Definition eines Speicherlecks!)

Aber beide zeigen sich durch andere Symptome
- Nicht freigegebener Speicher bei Programmende: z.B. wenn bei Programmende noch Zeugs übrigbleibt, das nicht befreit wurde. Bei modernen Betriebssystemen weniger ein Problem, trotzdem ärgerlich.

- Bei Programmende freigegebener Speicher, jedoch nicht zur Laufzeit: z.B. wenn durch eine kontinuierliche Wiederholung eines Programmteils (etwa einer Game-Loop) immer mehr Speicher reserviert wird, der zwar nicht verlorengeht (und somit am Ende des Programms wieder aufgeräumt wird), aber durch den der Speicherverbrauch der Anwendung mit der Zeit immer mehr steigt.

Das sind beides Memory Leaks (die Verwandtschaft der beiden Symptomatiken sollte offensichtlich sein, wenn nicht empfehle ich einen Wechsel des Berufs).

Grestorn
2007-10-17, 20:38:16
da kann ich mich nur wiederholen, dass du ja nichts verimissen kannst, was du nicht kennst. templates sind taeglich eine sehr nuetzliche hilfe bei der programmierung, und das fuer optimierungen, fuer sicherheit, fuer 'arschabwischer'-funktionen, um die meiste funktionalitaet abzubilden (so wie man es moechte) die andere sprachen wie z.b. java als eingebauten funktionsumfang bieten (z.b. reflection) und diese auch nach spass zu erweitern (z.b. memory layout der reflektierten objekte im ram reflektieren).

und ich denke coder rastet nur aus weil du deine meinung mal wieder pauschal als tatsache darstellst ;)

Ok, ich hab mich ja schon eines Besseren belehren lassen.

Ich glaube zwar weiterhin nicht, dass ich das jemals brauchen werde, inklusive irgendeiner meiner Kollegen im näheren und weiterem Umfeld. Aber es gibt auch Leute, die ganz anders denken, ganz andere Aufgaben haben und ganz andere Lösungen finden. Und für die wird das sicher eine tolle Sache sein.

Schade finde ich nur, dass mir Coda da auf meine Frage nach einem Beispiel eines sinnvollen Einsatz ein einzelnes Produkt hinwirft, das auch noch ein sehr spezielles Einsatzgebiet hat. Nur die wenigsten Entwickler benötigen jemals einen komplexen Parser, der mehr machen muss, als man mit einer Handvoll Methoden selbst schnell implementieren kann.

Ich hätte erhofft, dass er mir irgendein praktisches Problem nennt, das mir im Alltag auch mal begegnet und das ich mit C++ Templates deutlich eleganter als ohne lösen kann. Damit ich mit meinem begrenzten Horizont vielleicht auch was lerne.

Stattdessen bekomme ich nur beleidigten Rotz. Schade.

tokugawa
2007-10-17, 20:42:56
Ich hätte erhofft, dass er mir irgendein praktisches Problem nennt, das mir im Alltag auch mal begegnet und das ich mit C++ Templates deutlich eleganter als ohne lösen kann. Damit ich mit meinem begrenzten Horizont vielleicht auch was lerne.


Da kann ich dir einiges aufzählen:
- Singleton-Template
- Generic Factory-Template
- alle möglichen Collection-Klassen (die reine Nutzung der STL ist ja auch eine Nutzung von Templates, auch wenn man jetzt nicht selbst Templates deklariert, sondern sie nur nutzt), wo man das Rad nicht neu erfinden will. Wozu eine verkettete Liste neu schreiben für einen neuen contained type? Ist eine String-Liste jetzt wirklich soviel anders als eine Integer-Liste dass man denselben Scheiß zweimal schreiben muß?

Grestorn
2007-10-17, 20:45:51
Es gibt zwei Varianten von Memory Leaks. Beide haben gemein, dass Speicher der nicht mehr sinnvoll genutzt wird weiter belegt ist (logisch - das ist die genaue Definition eines Speicherlecks!)

Prinzipiell hast Du natürlich recht. Aber die 1.) Variante existiert bei einem Einsatz eines GC grundsätzlich nicht mehr.

Und die 2. Variante ist genau der Fall, den ich beschrieben habe, und der einzige, der mit einem GC noch vorkommen kann.

Was im Übrigen trotz CG passieren kann, ist das während des Programmlaufs andere Ressourcen, wie z.B. Dateilocks nicht freigegeben werden, weil man das Close vergessen hat und die Instanz nicht aus dem Scope fällt.

Grestorn
2007-10-17, 20:47:01
Da kann ich dir einiges aufzählen:
- Singleton-Template
- Generic Factory-Template
- alle möglichen Collection-Klassen (die reine Nutzung der STL ist ja auch eine Nutzung von Templates, auch wenn man jetzt nicht selbst Templates deklariert, sondern sie nur nutzt), wo man das Rad nicht neu erfinden will. Wozu eine verkettete Liste neu schreiben für einen neuen contained type? Ist eine String-Liste jetzt wirklich soviel anders als eine Integer-Liste dass man denselben Scheiß zweimal schreiben muß?

Für alle diese Beispiele reichen auch Generics.

tokugawa
2007-10-17, 20:47:15
Prinzipiell hast Du natürlich recht. Aber die 1.) Variante existiert bei einem Einsatz eines GC grundsätzlich nicht mehr.

Und die 2. Variante ist genau der Fall, den ich beschrieben habe, und der einzige, der mit einem GC noch vorkommen kann.


Genau. Die zweite ist auch die fiesere Variante.

Für alle diese Beispiele reichen auch Generics.

Wir reden hier von C++.

Grestorn
2007-10-17, 20:52:18
Wir reden hier von C++.

Blättere zurück im Thread: Die Diskussion war, wo C++ Vorteile gegenüber Java/C# hat. Es wurden Templates aufgeführt.

Darauf habe ich die These aufgestellt, dass es nichts sinnvolles gibt, was man mit Templates, nicht aber mit Generics lösen kann.

Coda hat mich eines Besseren belehrt, zumindest für sein Aufgabengebiet. Was meine tägliche Arbeit (und ich behaupte auch die von 99% aller SW-Entwickler) angeht, bleibe ich bei meiner These.

tokugawa
2007-10-17, 21:44:10
Blättere zurück im Thread: Die Diskussion war, wo C++ Vorteile gegenüber Java/C# hat. Es wurden Templates aufgeführt.

Darauf habe ich die These aufgestellt, dass es nichts sinnvolles gibt, was man mit Templates, nicht aber mit Generics lösen kann.

Coda hat mich eines Besseren belehrt, zumindest für sein Aufgabengebiet. Was meine tägliche Arbeit (und ich behaupte auch die von 99% alles SW-Entwickler) angeht, bleibe ich bei meiner These.

Tjo, nur ist die Frage "Templates vs Generics" in C++ irgendwie überflüssig.

Mir fällt allerdings eine andere praktsiche Anwendung von Templates ein, die sich mit Generics nicht lösen lässt: meine Vertex-Template-Klasse für Direct3D 9. Die bastelt mittels Metaprogrammierung automatisch eine Vertexdeklaration zusammen.

Demirug
2007-10-17, 22:00:42
Mir fällt allerdings eine andere praktsiche Anwendung von Templates ein, die sich mit Generics nicht lösen lässt: meine Vertex-Template-Klasse für Direct3D 9. Die bastelt mittels Metaprogrammierung automatisch eine Vertexdeklaration zusammen.


Das mache ich in .Net mit Attributen und Reflection.

Gast
2007-10-17, 23:04:08
Aber beide zeigen sich durch andere Symptome
- Nicht freigegebener Speicher bei Programmende: z.B. wenn bei Programmende noch Zeugs übrigbleibt, das nicht befreit wurde. Bei modernen Betriebssystemen weniger ein Problem, trotzdem ärgerlich.

- Bei Programmende freigegebener Speicher, jedoch nicht zur Laufzeit: z.B. wenn durch eine kontinuierliche Wiederholung eines Programmteils (etwa einer Game-Loop) immer mehr Speicher reserviert wird, der zwar nicht verlorengeht (und somit am Ende des Programms wieder aufgeräumt wird), aber durch den der Speicherverbrauch der Anwendung mit der Zeit immer mehr steigt.


Darf man mal fragen, was du immer mit deinem Programmende hast? Wenn der Prozess terminiert, wird automatisch der Speicher freigegeben.

Deinen zweiten Punkt kann ich ja nachvollziehen, aber auch hier die Frage von welchem Programmende du redest. Natürlich ist es ein Laufzeitproblem. Wenn du kontinuierlich (z.B. Loop) zur Laufzeit Speicher anforderst, aber diesen nicht wieder freigibst, so schrumft natürlich dein "freier" Speicher des virtueller Adressraum. Und genau das ist ein Laufzeitproblem und macht sich irgendwann auch zur Programmlaufzeit bemerkbar. Wenn der Prozess terminiert ist, ist das doch vollkommen uninteressant.

Und genau für letzten Fall beugt die VM vor, wenn man einmal davon ausgeht, dass die Objekte nur innerhalb der Loop erreichbar sind (lokal).

Demirug
2007-10-17, 23:14:10
Darf man mal fragen, was du immer mit deinem Programmende hast? Wenn der Prozess terminiert, wird automatisch der Speicher freigegeben.

Das war nicht immer so. Bei den alten 16 Bit Windows Versionen war der Speicher dann bis zum nächsten Neustart weg.

Und genau für letzten Fall beugt die VM vor, wenn man einmal davon ausgeht, dass die Objekte nur innerhalb der Loop erreichbar sind (lokal).

Ja nur leider kommt es eben manchmal auch bei Programmen mit einem CG aufgrund von Programmfehlern dazu das solche Objekte in einen globalen Context wandern

tokugawa
2007-10-17, 23:53:32
Darf man mal fragen, was du immer mit deinem Programmende hast? Wenn der Prozess terminiert, wird automatisch der Speicher freigegeben.


Was heißt hier "immer"? Ich hab's einmal erwähnt und dazugeschrieben (lesen kannst du doch oder?) dass es bei modernen Betriebssystemen kein großes Problem darstellt. Nichtsdestotrotz sollte man solche Leaks nicht haben, da diverse Memory-Leak-Tracker diese dann reporten und dann eventuell wichtigere Dinge dann verstecken (mal abgesehen davon dass man Laufzeit-Warnings gern wegkriegen würde).


Deinen zweiten Punkt kann ich ja nachvollziehen, aber auch hier die Frage von welchem Programmende du redest.


Terminierung des Prozesses, was sonst? Aber auch hier ist dieses Programmende dass du hier so betonst nicht als "wichtig" markiert.


Natürlich ist es ein Laufzeitproblem. Wenn du kontinuierlich (z.B. Loop) zur Laufzeit Speicher anforderst, aber diesen nicht wieder freigibst, so schrumft natürlich dein "freier" Speicher des virtueller Adressraum. Und genau das ist ein Laufzeitproblem und macht sich irgendwann auch zur Programmlaufzeit bemerkbar. Wenn der Prozess terminiert ist, ist das doch vollkommen uninteressant.


Es ist kein großes Problem, aber es ist trotzdem nicht uninteressant.


Und genau für letzten Fall beugt die VM vor, wenn man einmal davon ausgeht, dass die Objekte nur innerhalb der Loop erreichbar sind (lokal).

Das sind sie in komplexeren Systemen eigentlich nie (global verfügbare, laufzeit-persistente Objekte wie Resourcen-Listen in Spielen oder ähnliches).

Wenn man etwa in einem Spiel so viele Sound-Voices erzeugt im Laufe des Spiels, die alle nicht zerstört werden sondern vom Voice-Manager in einer Liste weiterverwaltet werden, dann ist das auch ein Memoryleak.

Das mache ich in .Net mit Attributen und Reflection.

Viele Wege führen nach Rom.

maximAL
2007-10-18, 00:08:58
Naja die Metasprache die sich daraus ergibt ist schon funktional.
inwiefern? weil man auf der meta-ebene nur non-mutable konstrukte benutzt? das ist zwar auch ein merkmal funktionaler programmierung, aber noch längst nicht dasselbe.

Coda
2007-10-18, 00:12:51
Du machst Schleifen z.B. nur über Rekursion usw.

Gast
2007-10-18, 07:59:51
und ich denke coder rastet nur aus weil du deine meinung mal wieder pauschal als tatsache darstellst ;) Look who's talking. :) Ihr Beide unterscheidet Euch da nicht sonderlich von außen betrachtet. Und Coda beginnt leider inzwischen auch jeden 3ten Beitrag mit einem "Quatsch, Blödsinn, Schwachsinn". :(

Muß hier eigentlich jeder immer recht haben? Wissen existiert sowieso nicht sondern nur Meinungen, von daher kann man einige Dinge auch mal etwas gelassener sehen und trotzdem vernünftig miteinander sprechen.

micki
2007-10-18, 08:00:23
Das ist doch schlicht völlig falsch. Nach Deiner Definition hätte jedes Programm Speicherlecks. nur wenn programmierer speicher allokiert liessen den sie als deallokiert ansehen. denn nichts anderes ist ein speicherleck, ein wegen einem programmfehlers noch allokierter speicher der haette freigegeben sein sollen.


Nein, ich habe einen Fehler in der Liste. Wenn ich über sie iteriere bekomme ich ein zusätzliches Element, das ich eigentlich dachte entfernt zu haben.

Es ist aber immer noch das Element, vollständig und intakt. Das heißt, ich kann darauf zugreifen, lesend und schreibend ohne Seiteneffekte. Und diesen Fehler zu debuggen ist sehr leicht: Jedesmal passiert genau das gleiche, keine Zufallseffekte wie bei echten C++ Wild Pointers. wie ich schon sagte, behaupte nicht es waere leicht, da du garnicht genug informationen hast, somit es ist ne BS behauptung.

Stell Dir vor, Du hättest in C++ zwar den Pointer deleted, aber vergessen ihn auf NULL zu setzen. Die Konsequenzen sind katastrophal und je nach dem wie die Objekte im Speicher verteilt sind, vollkommen zufällig!
wenn dein programm deswegen outofmemory geht ist es genau so katastrophal.

Gast
2007-10-18, 08:07:55
Das war nicht immer so. Bei den alten 16 Bit Windows Versionen war der Speicher dann bis zum nächsten Neustart weg.


Das ist klar, aber hier wird ja über C#/CLR und C++ verglichen. Folglich muss man zwangsweise auch mit einem halbwegs aktuellen OS argumentieren/vergleichen.

micki
2007-10-18, 08:10:32
Auch wenn ich die gesamte Diskussion als ziemlich kindisch empfinde, möchte ich hierzu Christopher Brumme aus dem Microsoft CLR-Team zitieren:
:lol: ja, ueber das marketing von MS lach ich auch gerne :). die haben mir schon die bloedesten antworten gegeben. dieses "Ist genau so schlecht" ist ja noch harmlos, wegen C# performance auf x360 meinten sie "Ist irrelevant da die meisten (hobby-)spiele eh GPU-limitiert sind" (deswegen spielt man ja auch spiele bei 1600*1200 mit 4AA*hehe*) und den BS mit "VM+GC ist schneller als pur c++" usw. hat beim BS-Bingo schon ne eigene zeile fuer sich reserviert *hehe*
Wie demirurg sagte, ist virtual-funktion in C# ein no-go. und ich koennte mir nicht vorstellen fuer jeder Virtual funktion noch ne seperate lokale funktion zu implementieren(mit selber funktionalitaet) damit mir niemand unter den fuessen die virtuelle funktion wegziehen kann (ohne dass ich es weiss und ohne dass der andere weiss das ich die funktion nutze). man muss sich ja nur mal ne neue lib-version ziehen von der man klassen ableitet und schon sitz man ewigkeiten um soeinen fehler zu finden nur weil jemand die lokale funktion nutzen wollte ohne sie redundant zu implementieren. :eek:

Grestorn
2007-10-18, 08:15:11
nur wenn programmierer speicher allokiert liessen den sie als deallokiert ansehen. denn nichts anderes ist ein speicherleck, ein wegen einem programmfehlers noch allokierter speicher der haette freigegeben sein sollen.

Mit einem GC kann man keinen Speicher als "deallokiert" ansehen.

wie ich schon sagte, behaupte nicht es waere leicht, da du garnicht genug informationen hast, somit es ist ne BS behauptung.
Ich behaupte das, weil ich in meinem Leben schon genügend Bugs durch kaputte Speicherverwaltung suchen musste. Manchmal meine eigenen, viel öfter aber die anderer. Und das kann richtig scheiße sein.

Ich will das eigentlich nicht rauskehren, aber wenn Du mir unterstellst, Bullshit zu sagen, bleibt mir ja nichts anderes. Ich programmiere seit 1987 in C, seit 1989 professionell (sprich: die Programme werden verkauft und ich lebe davon), seit 1995 in C++ und seit 2000 in Java.

Ich weiß genau, wie schwer es ist, einen nicht reproduzierbaren Bug in C++ zu finden, der sich letztlich als Problem mit der Speicherverwaltung rausgestellt. Ich weiß auch genau, dass solche Fehler in Java schlicht nicht vorkommen. Deine Konstruktion kommt nicht vor (u.a. weil man eh nur fertige Collection-Klassen benutzt) und selbst wenn man in einer eigenen Objektstruktur einen solchen Fehler macht, ist er schnell gefunden.

Also hör auf von Dingen zu schwadronieren, von denen Du ganz offensichtlich keine Ahnung hast. Du magst ein guter C++ Programmierer sein, aber mit Java/C# hast Du ganz offensichtlich kaum Praxiserfahrung.

Xmas
2007-10-18, 08:45:27
:lol: ja, ueber das marketing von MS lach ich auch gerne :). die haben mir schon die bloedesten antworten gegeben. dieses "Ist genau so schlecht" ist ja noch harmlos
Dann erkläre doch mal warum das C++-Verhalten in diesem Fall objektiv besser ist als das C#-Verhalten.

micki
2007-10-18, 09:36:48
Mit einem GC kann man keinen Speicher als "deallokiert" ansehen. klar kannst du das, sobald es keine reference drauf gibt, ist er freigegeben. hast du eine reference darauf vergessen, obwohl du den speicher deferenzieren wolltest damit er 'frei' wird, hast du ein memleak.


Ich behaupte das, weil ich in meinem Leben schon genügend Bugs durch kaputte Speicherverwaltung suchen musste. Manchmal meine eigenen, viel öfter aber die anderer. Und das kann richtig scheiße sein. es ist leicht und richtig scheisse... widerspricht sich das nicht?


Ich will das eigentlich nicht rauskehren, aber wenn Du mir unterstellst, Bullshit zu sagen, bleibt mir ja nichts anderes. Ich programmiere seit 1987 in C, seit 1989 professionell (sprich: die Programme werden verkauft und ich lebe davon), seit 1995 in C++ und seit 2000 in Java. und trotzdem bleibt deine aussage BS da du behauptest es waere leicht diesen bug zu finden obwohl es ein rein konstruierter bug ist ohne dass du ihn analysieren koenntest. du kannst 100jahre erfahrung haben und trotzdem wird kristalkugel-debuggen BS bleiben. (sorry wenn dich das angreift, aber es ist echt unsinn einen rein ausgedachten bug als leicht zu klassifizieren).



Also hör auf von Dingen zu schwadronieren, von denen Du ganz offensichtlich keine Ahnung hast. Du magst ein guter C++ Programmierer sein, aber mit Java/C# hast Du ganz offensichtlich kaum Praxiserfahrung.
muss ich auch meinen jonny raushaengen lassen dass ich mit java (und j++) seit der ersten veroeffentlichung gearbeitet habe, bis heute arbeite, um damit gewichtung zu verleihen dass du BS erzaehlst wenn du einen rein ausgedachten bug als leicht fixbar klassifizierst?

micki
2007-10-18, 09:39:04
Dann erkläre doch mal warum das C++-Verhalten in diesem Fall objektiv besser ist als das C#-Verhalten.
:lol: wenn du mir zusagst dass du dem nur widersprichst wenn du's auch beweisen kannst?


edit: btw. MS zu zittieren ist kein beweis. die featurelist aufzuzaehlen ala VM+RC hat schnellere allokation deswegen ist es schneller zaehlen auch nicht als beweis. ;)

Gast
2007-10-18, 09:55:07
Wie demirurg sagte, ist virtual-funktion in C# ein no-go.


Die Rede war ja auch vom Aufruf aus dem Konstruktor heraus! Warum verallgemeinerst du jetzt generell virtuelle Methoden als no-go?


und ich koennte mir nicht vorstellen fuer jeder Virtual funktion noch ne seperate lokale funktion zu implementieren(mit selber funktionalitaet)


Man könnte aber auch aus der virtuellen Methode eine Methode mit eben dieser Funktionalität aufrufen. Dann spart man sich eine mehrfache Implementierung der selben Logik.


damit mir niemand unter den fuessen die virtuelle funktion wegziehen kann (ohne dass ich es weiss und ohne dass der andere weiss das ich die funktion nutze).


Das ist ja gerade der Sinn, dass Klasse in der untersten Vererbungshierarchie auf Logik von Klassen aus der obersten Vererbungshierarchie zugreifen können.

Vielleicht habe ich dich jetzt auch missverstanden und du meinst etwas ganz anderes, allerdings gleichen deine Formulierungen auch eher einem Rätselbuch.

Grestorn
2007-10-18, 09:58:33
klar kannst du das, sobald es keine reference drauf gibt, ist er freigegeben. hast du eine reference darauf vergessen, obwohl du den speicher deferenzieren wolltest damit er 'frei' wird, hast du ein memleak.

Man kann (mit GC) keine Referenz "vergessen". Das geht nicht. Schließlich ist man nicht gezwungen, Referenzen "freizugeben". Sie fallen entweder von sich aus aus dem Scope, werden ersetzt (und dann ist das bisher referenzierte Objekt automatisch frei) oder bleiben während des gesamten Programmablauf erhalten.

Nur wenn man dynamische Datenstrukturen hat und die ständig nur wachsen lässt, steigt die Zahl der Referenzen. Aber das schreibe ich ja auch ständig.

es ist leicht und richtig scheisse... widerspricht sich das nicht?
Es ist richtig scheiße in C++.
Es ist richtig leicht in Java.

Manchmal zweifle ich schon an Deinen Fähigkeiten zu lesen.

und trotzdem bleibt deine aussage BS da du behauptest es waere leicht diesen bug zu finden obwohl es ein rein konstruierter bug ist ohne dass du ihn analysieren koenntest. du kannst 100jahre erfahrung haben und trotzdem wird kristalkugel-debuggen BS bleiben. (sorry wenn dich das angreift, aber es ist echt unsinn einen rein ausgedachten bug als leicht zu klassifizieren).
Ein Bug ist immer dann recht leicht zu finden, wenn er sich deterministisch verhält. Und das macht der von Dir konstruierte Bug in Java immer!

Ein Fehler im Speichermanagement in C++ ist im Allgemeinen aber nicht deterministisch. Denn das Ergebnis hängt davon ab wie die Objekte im Speicher angeordnet sind, und das lässt sich eben nicht eindeutig vorhersagen.

Das versuche ich Dir schon die ganze Zeit nahe zu bringen. Statt dessen antwortest Du nur mit "Bullshit", obwohl Dir offensichtlich die wichtigsten Grundlagen fehlen.

muss ich auch meinen jonny raushaengen lassen dass ich mit java (und j++) seit der ersten veroeffentlichung gearbeitet habe, bis heute arbeite, um damit gewichtung zu verleihen dass du BS erzaehlst wenn du einen rein ausgedachten bug als leicht fixbar klassifizierst?

Lass ihn nur raushängen, Deinen Jonny, aber wenn Dir die fundamentalen Unterschiede von Java und C++ in all den Jahren nicht klargeworden sind, dann ist es nicht viel her mit dem ärmsten.

Demirug
2007-10-18, 09:59:32
Wie demirurg sagte, ist virtual-funktion in C# ein no-go. und ich koennte mir nicht vorstellen fuer jeder Virtual funktion noch ne seperate lokale funktion zu implementieren(mit selber funktionalitaet) damit mir niemand unter den fuessen die virtuelle funktion wegziehen kann (ohne dass ich es weiss und ohne dass der andere weiss das ich die funktion nutze). man muss sich ja nur mal ne neue lib-version ziehen von der man klassen ableitet und schon sitz man ewigkeiten um soeinen fehler zu finden nur weil jemand die lokale funktion nutzen wollte ohne sie redundant zu implementieren. :eek:

Ich sagte sie sind evil und das trifft sowohl auf C++ wie auch C# zu. Wobei das C# Verhalten zu mindestens einheitlich ist. Zudem bietet man virtuelle Funktionen in einer Lib doch gerade deswegen an damit sie überschrieben werden können.

micki
2007-10-18, 10:03:06
Die Rede war ja auch vom Aufruf aus dem Konstruktor heraus! Warum verallgemeinerst du jetzt generell virtuelle Methoden als no-go?ich dachte das waere offensichtlich dass ich es darauf beziehe. oder haben wir ploetzlich einen themenwechsel gehabt? virtuelle aufrufe aus dem c-tor. ja.



Man könnte aber auch aus der virtuellen Methode eine Methode mit eben dieser Funktionalität aufrufen. Dann spart man sich eine mehrfache Implementierung der selben Logik.klar, kann man, man bastelt sich fuer jede virtuelle funktion noch ne pimpl. ich hoffe ich bin aber nicht der einzige der sich bei der idee an den kopf fasst.



Vielleicht habe ich dich jetzt auch missverstanden und du meinst etwas ganz anderes, allerdings gleichen deine Formulierungen auch eher einem Rätselbuch.
ich sprach die ganze zeit ueber das selbe thema (http://www.forum-3dcenter.org/vbulletin/showthread.php?p=5940470#post5940470) in bezug auf virtuelle funktionen. denn weitere unterschiede gibt es nicht bei c++ und java/c# in bezug auf virtuelle funktionen.

micki
2007-10-18, 10:09:05
Ich sagte sie sind evil und das trifft sowohl auf C++ wie auch C# zu. Zudem bietet man virtuelle Funktionen in einer Lib doch gerade deswegen an damit sie überschrieben werden können.
ja, nur um es sicher zu machen, musst du in c# eine virtual und eine non-virtual funktion implementieren, nur damit du sie mal aus dem ctor aufrufen kannst. bei c++ kannst du und der compiler drauf verlassen dass der aufruf im bekannten scope bleibt.
und fuer die die das nicht wissen (und ich hab so den eindruck dass es hier nicht sonderlich viele wusten), kann das zu sehr boesen fehlern fuehren in c#.

Wobei das C# Verhalten zu mindestens einheitlich ist. in C++ kannst du per definition bzw standard nicht auf (noch) uninitialisierte bereiche zugreifen. was ist daran uneinheitlich? *aufschlauchsteht*

Grestorn
2007-10-18, 10:19:13
ja, nur um es sicher zu machen, musst du in c# eine virtual und eine non-virtual funktion implementieren, nur damit du sie mal aus dem ctor aufrufen kannst. bei c++ kannst du und der compiler drauf verlassen dass der aufruf im bekannten scope bleibt.
?! Wieso sollte man das tun?

Man muss doch lediglich die Initialisierungsaufgaben, die virtuell laufen sollen, in eine zweite "init" Methode auslagern und bei jeder Instanziierung daran denken, eben diese init-Methode zu rufen...

und fuer die die das nicht wissen (und ich hab so den eindruck dass es hier nicht sonderlich viele wusten), kann das zu sehr boesen fehlern fuehren in c#.
In der Tat kennen das Problem nur wenige, aber gerade in diesem Thread hatte ich den Eindruck, dass alle davon wussten.

in C++ kannst du per definition bzw standard nicht auf (noch) uninitialisierte bereiche zugreifen. was ist daran uneinheitlich? *aufschlauchsteht*
Ist die Vorgehensweise beim Aufbau der vtable in C++ genau im Standard beschrieben? Ich bin mir da nicht so sicher. Alle C++-Kompiler die ich kenne verhalten sich zwar so, aber ob es genau so definiert ist, wüsste ich so nicht zu sagen.

Stroustrup-Auswendig-Kenner vor!

Demirug
2007-10-18, 10:30:36
Die Tatsache das C++ erst die Konstruktoren der Basisklassen ausführt und dann die eigenen Variablen initialisiert macht dieses uneinheitliche Verhalten doch erst notwendig. Mit uneinheitlich meine ich das sich eine virtuelle Funktion wenn sie aus dem Konstruktor aufgerufen wird eben nicht wie eine virtuelle Funktion verhält.

Ich habe auch schon Fehler gesehen die draus entstanden dass der Programmierer eben diese Ausnahme von der Regel nicht berücksichtigt hat.

Letzten Endes ist es aber egal ob man nun das C++ oder das C# model hat. Beide haben ihre Tücken. Ich bleibe dabei das virtuelle Funktionsaufrufe im Konstruktor evil sind.

micki
2007-10-18, 10:36:45
?! Wieso sollte man das tun?
Man könnte aber auch aus der virtuellen Methode eine Methode mit eben dieser Funktionalität aufrufen. Dann spart man sich eine mehrfache Implementierung der selben Logik.



Man muss doch lediglich die Initialisierungsaufgaben, die virtuell laufen sollen, in eine zweite "init" Methode auslagern und bei jeder Instanziierung daran denken, eben diese init-Methode zu rufen... wie soll ich mir das vorstellen? jeder c-tor ruft dann einmal init auf? welches init? und wie kann dieses Init dafuer sorgen dass nur funktionen aus dem bekannten scope aufgerufen werden? oder meinst du man sollte den code nochmal redundant einbauen?


In der Tat kennen das Problem nur wenige, aber gerade in diesem Thread hatte ich den Eindruck, dass alle davon wussten.
http://www.forum-3dcenter.org/vbulletin/showpost.php?p=5940640&postcount=123
mir scheint es war nicht so ganz klar wie sich die sprachen verhalten, obwohl man natuerlich annahmen machen koennte.

Ist die Vorgehensweise beim Aufbau der vtable in C++ genau im Standard beschrieben? Ich bin mir da nicht so sicher. Alle C++-Kompiler die ich kenne verhalten sich zwar so, aber ob es genau so definiert ist, wüsste ich so nicht zu sagen. jap, das verhalten ist genau definiert. die VTable an sich spielt dabei keine so grosse rolle im c-tor selbst, da du zur compile time, wenn der scope bekannt ist, devirtualisieren kannst, trotzdem wird der vtable eintrag korrekt gemacht.

micki
2007-10-18, 10:42:21
Die Tatsache das C++ erst die Konstruktoren der Basisklassen ausführt und dann die eigenen Variablen initialisiert macht dieses uneinheitliche Verhalten doch erst notwendig. Mit uneinheitlich meine ich das sich eine virtuelle Funktion wenn sie aus dem Konstruktor aufgerufen wird eben nicht wie eine virtuelle Funktion verhält. sie verhalten sich wie virtuelle funktionen aber nur bis zum bekannten scope... vom c-tor selbst sind es dann eigentlich keine virtuellen funktionen (fuer ausserhalb schon)

Grestorn
2007-10-18, 10:46:29
wie soll ich mir das vorstellen? jeder c-tor ruft dann einmal init auf? welches init? und wie kann dieses Init dafuer sorgen dass nur funktionen aus dem bekannten scope aufgerufen werden? oder meinst du man sollte den code nochmal redundant einbauen?

Nein, nicht der ctor ruft die init(), denn das geht ja eben nicht ohne unerwartete Nebeneffekte.

Also statt:


class blubber
{
public blubber()
{
virtFunct();
}

protected virtFunct()
{
// Hier sich wundern, warum in abgeleiteten Klassen initialisierte Member
// erst nach dem Durchlauf dieser Methode initialsiert werden
}
}


Machst Du:

class blubber
{
public blubber()
{
}

public init()
{
virtFuct();
}


protected virtFunct()
{
// Tut wie erwartet
}
}


Wie ich schon schrieb, muss man dann nur beim Instantiieren der Klasse daran denken, auch die init() Methode zu rufen. Nicht optimal, aber oft die einzig brauchbare Lösung.

Grestorn
2007-10-18, 10:48:14
sie verhalten sich wie virtuelle funktionen aber nur bis zum bekannten scope... vom c-tor selbst sind es dann eigentlich keine virtuellen funktionen (fuer ausserhalb schon)

Ich muss zugeben, dass das Verhalten in C++ hier "konsequenter" ist, als das in Java/C++.

Trotzdem würde ich virtuelle Methodenaufrufe in Konstruktoren meiden wie der Teufel das Weihwasser, egal in welcher Sprache.

Demirug
2007-10-18, 10:50:06
sie verhalten sich wie virtuelle funktionen aber nur bis zum bekannten scope... vom c-tor selbst sind es dann eigentlich keine virtuellen funktionen (fuer ausserhalb schon)

Ich will jetzt keine Haarspalterie betreiben aber wenn beim Aufruf einer „virtuellen“ Funktion niemals die überschriebene Version ausgeführt werden kann verhält sie sich eben nicht wie eine virtuelle Funktion. Das Ganze wird übrigens erst richtig lustig wenn man im Konstruktor eine Funktion außerhalb der eigentlichen Klasse aufruft die im guten Glauben dann auf eine virtuelle Funktion zugreift.

micki
2007-10-18, 10:54:20
Ich will jetzt keine Haarspalterie betreiben aber wenn beim Aufruf einer „virtuellen“ Funktion niemals die überschriebene Version ausgeführt werden kann verhält sie sich eben nicht wie eine virtuelle Funktion.doch, es wird die ueberschriebene bis zum bekannten scope aufgerufen Das Ganze wird übrigens erst richtig lustig wenn man im Konstruktor eine Funktion außerhalb der eigentlichen Klasse aufruft die im guten Glauben dann auf eine virtuelle Funktion zugreift.
genau das meinte ich mit "(fuer ausserhalb schon)", deswegen ist das ganze keine haarspalterei. wenn der aufruf von aussen kommt, wird die virtuelle funktion aufgerufen deren c-tor auch schon aufgerufen wurde/wird. dabei kann es ja schon mehrere 'ueberschreibungen' gegeben haben. es wird ja nicht immer die root-implementierung der funktion aufgerufen (denn dann waere es ja wirklich das uneinheitliche verhalten von virtuellen funktionen).

Demirug
2007-10-18, 10:54:33
Ich muss zugeben, dass das Verhalten in C++ hier "konsequenter" ist, als das in Java/C++.

Wieso sollte es konsequenter sein? Es ist doch nur eine Notwendigkeit um zu vermeiden das eine virtuelle Funktion auf uninitialisierte Werte zugreifet. Bei .Net darf es diese ja aufgrund der Spezifikation nicht geben. Ich könnte genauso gut sagen C# macht konsequent das was ich will. Es wird die virtuelle Funktion des tatsächlichen Objekts ausgeführt.

micki
2007-10-18, 10:57:57
Nein, nicht der ctor ruft die init(), denn das geht ja eben nicht ohne unerwartete Nebeneffekte.

Also statt:


class blubber
{
public blubber()
{
virtFunct();
}

protected virtFunct()
{
// Hier sich wundern, warum in abgeleiteten Klassen initialisierte Member
// erst nach dem Durchlauf dieser Methode initialsiert werden
}
}


Machst Du:

class blubber
{
public blubber()
{
}

public init()
{
virtFuct();
}


protected virtFunct()
{
// Tut wie erwartet
}
}


Wie ich schon schrieb, muss man dann nur beim Instantiieren der Klasse daran denken, auch die init() Methode zu rufen. Nicht optimal, aber oft die einzig brauchbare Lösung.
das verhalten waere dann doch wirklich gefaehrlich. damit mein ich nicht nur dass jemand aus versehen vergessen koennte init aufzurufen oder das temporaere variabeln komplett uninitialisiert bleiben (da ruft ja niemand init auf, selbst wenn der copy-ctor kommt), sondern auch dass wenn jemand mal am root der vererbungshierarchy im init etwas einbaut, ruft das niemand auf. oder ueberseh ich da etwas?

Grestorn
2007-10-18, 11:07:12
das verhalten waere dann doch wirklich gefaehrlich. damit mein ich nicht nur dass jemand aus versehen vergessen koennte init aufzurufen oder das temporaere variabeln komplett uninitialisiert bleiben (da ruft ja niemand init auf, selbst wenn der copy-ctor kommt), sondern auch dass wenn jemand mal am root der vererbungshierarchy im init etwas einbaut, ruft das niemand auf. oder ueberseh ich da etwas?

Na, grundsätzlich sollte in solchen inits in abgeleiteten Klassen immer die Methode der Superklasse aufgerufen werden, also:

super.init();

Ein weiterer Nachteil von C++ übrigens, denn da muss ich den Namen der Superklasse explizit angeben mit

Basiklasse::init()

was ein Refactoring schwerer macht und eine weitere Fehlerquelle ist.

Was Du hier mit temp. Variablen meinst, ist mir völlig unklar. Das musst Du mir an einem Beispiel erläutern.

Grestorn
2007-10-18, 11:10:19
Wieso sollte es konsequenter sein?

Du hast sicher recht mit Deiner Vermeidungsstrategie.

Dennoch erscheint es mir "nachvollziehbarer" zu sagen, in einem Konstruktor ist die Klasse nur bis zur aktuellen Hierarchie aufgebaut und es werden keinerlei weitere Überschreibungen berücksichtigt, Punkt.

In C# werden zwar Überschreibungen von abgeleiteten Klassen auch im Konstruktor berücksichtigt, aber fieserweise dennoch die abgeleiteten Klassen enthaltenen Initializer erst NACH dem Durchlauf des Konstruktors der Basisklasse durchlaufen. Das ist m.E. asymmetrisch und inkonsequent.

Gast
2007-10-18, 11:40:26
In C# werden zwar Überschreibungen von abgeleiteten Klassen auch im Konstruktor berücksichtigt, aber fieserweise dennoch die abgeleiteten Klassen enthaltenen Initializer erst NACH dem Durchlauf des Konstruktors der Basisklasse durchlaufen. Das ist m.E. asymmetrisch und inkonsequent.

Hä, was für Schwachsinn erzählst du? Wenn im Konstruktor der abgeleiteten Klasse die Init Methode steht und ein Objekt der abgeleiteten Klasse erstellt wird, dann ist es logisch, dass erst der Konstruktur der Basisklasse aufgerufen wird und danach der Konstruktur der abgeleiteten Klasse. Und folgich logisch ist es, dass die besagte Init Methode dann eben nach dem Konstruktor der Basisklasse aufgerufen wird.

Gast
2007-10-18, 12:47:36
Na, grundsätzlich sollte in solchen inits in abgeleiteten Klassen immer die Methode der Superklasse aufgerufen werden, also:

super.init();aber dann hast du doch genau das selbe c-tor verhalten und nichts gewonnen. die root-.init-funktion ruft immer noch vom untersten kind die function auf ohne dass die child init durchgelaufen ist (da du ja vermutlich als erstes super.init() aufrufen musst.


Ein weiterer Nachteil von C++ übrigens, denn da muss ich den Namen der Superklasse explizit angeben mit
Basiklasse::init()
was ein Refactoring schwerer macht und eine weitere Fehlerquelle ist.

es ist nicht mehr fehlerquelle als wenn du beim refactorn super.init aus versehen verschiebst und es aufgerufen wird ohne dass du es wolltest, was bei c++ nicht gehen wuerde sofern es nicht wirklich die richtige basisklasse ist.
beide seiten koennen evil sein.


Was Du hier mit temp. Variablen meinst, ist mir völlig unklar. Das musst Du mir an einem Beispiel erläutern.
z.b.
.SetColor(new Color(255,255,255));
bzw
.SetColor(0xffff);//implizieter Color cast
damit sowas nicht passiert braeuchtest du fuer alle objekte factories... hmm... irgendwie sickert mir das ganze konzept nicht ein was es am ende bringt. hm.

micki
2007-10-18, 12:48:18
2007-10-18, 12:47:36 war ich, damn cookies

Grestorn
2007-10-18, 13:10:32
Hä, was für Schwachsinn erzählst du? Wenn im Konstruktor der abgeleiteten Klasse die Init Methode steht und ein Objekt der abgeleiteten Klasse erstellt wird, dann ist es logisch, dass erst der Konstruktur der Basisklasse aufgerufen wird und danach der Konstruktur der abgeleiteten Klasse. Und folgich logisch ist es, dass die besagte Init Methode dann eben nach dem Konstruktor der Basisklasse aufgerufen wird.

Das habe ich ja nie bezweifelt.

Folgendes Beispiel:


public class Basis
{
protected int a = 0;

public Basis()
{
virtFunct();

System.out.println("A = " + a);
}

public void virtFunct()
{
}
}


public class Sub extends Basis
{
private int b = 100;

public Basis()
{
super();
}

public void virtFunct()
{
a = b;
}

public static void main()
{
Sub cls = new Sub();
}
}




Was meinst Du, wird nach ausführung der Main-Methode auf dem Bildschirm stehen?

Tipp: Es ist nicht 100.

Grestorn
2007-10-18, 13:17:42
aber dann hast du doch genau das selbe c-tor verhalten und nichts gewonnen. die root-.init-funktion ruft immer noch vom untersten kind die function auf ohne dass die child init durchgelaufen ist (da du ja vermutlich als erstes super.init() aufrufen musst.

Doch, ich habe gewonnen, dass alle Membervariablen in der Methode init() korrekt initialisiert sind. Siehe mein Beispiel in dem vorhegehenden Posting, bei dem das nicht so ist.

es ist nicht mehr fehlerquelle als wenn du beim refactorn super.init aus versehen verschiebst und es aufgerufen wird ohne dass du es wolltest, was bei c++ nicht gehen wuerde sofern es nicht wirklich die richtige basisklasse ist.
beide seiten koennen evil sein.

Kaum. Bei Java kann man keinen Scope angeben, wenn man die Basisklasse ruft, dann kann man immer nur die eine direkte Basisklasse rufen, nicht eine in der Hierarchie noch weiter oben liegende. Und das ist gut so.


z.b.
.SetColor(new Color(255,255,255));
bzw
.SetColor(0xffff);//implizieter Color cast
damit sowas nicht passiert braeuchtest du fuer alle objekte factories... hmm... irgendwie sickert mir das ganze konzept nicht ein was es am ende bringt. hm.

Implizite Casts gibt es in Java nicht, weil es keine überladenen Cast-Operatoren (oder irgendwelche anderen überladenen Operatoren) gibt. Das ist tatsächlich in manchen Situationen schade, denn man kann wirklich nette Sachen mit überladenen Operatoren anstellen.

Andererseits kann es den Code auch absolut unlesbar machen.

Gast
2007-10-18, 13:29:22
Tipp: Es ist nicht 100.

Bei einem C#/.NET Programm - wovon auch hier die ganze Zeit die Rede ist - kommt exakt 100 raus!

Grestorn
2007-10-18, 13:38:39
Bei einem C#/.NET Programm - wovon auch hier die ganze Zeit die Rede ist - kommt exakt 100 raus!

Das Beispiel ist aus Java. Wie genau sich C# verhält habe ich hier nie probiert.

Was natürlich meiner Antwort an Demirug, wo ich explizit von C# gesprochen habe, widerspricht. Sorry. Ich dachte, dass sich C# und Java hier gleich verhalten. Mein Fehler.

Kabelsalat
2007-10-18, 18:37:39
In .Net lässt sich der Basiskonstruktor nicht explizit aufrufen. Es ist nur der implizite Aufruf mittels entsprechender Konstruktordefinition möglich:


public Sub : base()
{ }


Der Basiskonstruktor wird vor dem momentanen Konstruktor (hier Sub) ausgeführt. Der Basiskonstruktor ruft dann virtFunct auf, das wiederum a mit dem Wert von b initialisiert. b wird jedoch vom Standardkonstruktor der Klasse Sub implizit auf 100 initialisiert, davor besitzt es den Wert 0. Da der Konstruktor der Klasse Sub noch nicht aufgerufen wurde, folgt a = 0 und damit die Ausgabe 0.

tokugawa
2007-10-18, 19:08:27
wegen C# performance auf x360 meinten sie "Ist irrelevant da die meisten (hobby-)spiele eh GPU-limitiert sind" (deswegen spielt man ja auch spiele bei 1600*1200 mit 4AA*hehe*)


Naja, dass die meisten Spiele eher GPU-limitiert sind, wenn sie viele Effekte reinrotzen (wobei das ja sogar auf "Hobby"-Spiele zutrifft, die sind heutzutage auch aufwändiger als man glaubt, speziell bei Grafikeffekten/Techniken, die relativ kostensparend eingebaut werden können im Vergleich zu Content), entspricht ja der Wahrheit. Das kann dir jeder Experte im Bereich Realtime-Rendering bestätigen.

Microsofts Research-Abteilung ist jedenfalls seriös und man kann mit denen sachlich diskutieren (wobei ich hier hauptsächlich die Leute um den Microsoft-Researcher Peter-Pike Sloan meine, falls du den kennst. In der Computergrafik-Forschung ein sehr bekannter Name).

Gast
2007-10-18, 19:56:02
In .Net lässt sich der Basiskonstruktor nicht explizit aufrufen. Es ist nur der implizite Aufruf mittels entsprechender Konstruktordefinition möglich:


public Sub : base()
{ }


Der Basiskonstruktor wird vor dem momentanen Konstruktor (hier Sub) ausgeführt. Der Basiskonstruktor ruft dann virtFunct auf, das wiederum a mit dem Wert von b initialisiert. b wird jedoch vom Standardkonstruktor der Klasse Sub implizit auf 100 initialisiert, davor besitzt es den Wert 0. Da der Konstruktor der Klasse Sub noch nicht aufgerufen wurde, folgt a = 0 und damit die Ausgabe 0.

Schön, so viel geschrieben und trotzdem falsch. Hast du das überhaupt mal ausprobiert? Und b wird hier auch nicht vom ctor initialisiert, sondern auf Klassenebene. Und selbst wenn dort nicht 100 zugewiesen wäre, würde es immer noch nicht im ctor initialisiert werden, weil es ein Wertetyp ist. Außer man macht das explizit, aber dann findet intern eine doppelte Initialisierung statt. Und es kommt immer noch 100 heraus! Hier mal der Code bevor noch mehr Unwissende Unsinn erzählen.


using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Class2 c = new Class2();
Console.ReadLine();
}
}

public class Class1
{
protected int a = 0;

public Class1()
{
Console.WriteLine("Class1");
Func();
Console.WriteLine("A = " + a.ToString());
}

protected virtual void Func()
{

}
}

public class Class2 : Class1
{
private int b = 100;

public Class2() : base()
{
Console.WriteLine("Class2");
}

protected override void Func()
{
a = b;
}
}
}


Im übrigen ist der base() Aufruf ein expliziter Aufruf und kein impliziter Aufruf. Implizit wird die Basisklasse nämlich auch ohne Angabe von base() als erstes aufgerufen. Das hat bei einem Standard ctor auch wenig sind, sondern wird i.d.R. nur verwendet, wenn man Parameter zu den Basis ctors durchrouten möchte.

Kabelsalat
2007-10-18, 20:20:39
Was explizit und implizit betrifft, habe ich mich tatsächlich falsch ausgedrückt. Ich hätte schreiben sollen, dass man Konstruktoren nicht direkt aufrufen kann, sondern bloß durch eine entsprechende Konstruktordefinition.

Was das Ergebnis betrifft hast du augenscheinlich recht, allerdings versetzt mich das in Erstaunen: M.E. wird die Initialisierung von Instanzvariablen durch einen (notfalls implizit erstellten) Konstruktor übernommen. Reflector zeigt etwa auch, dass Class2..ctor() entsprechend ergänzt wurde. Class2..ctor() sollte jedoch erst nach Class1..ctor() und damit auch nach dem Aufruf der Methode Class2.Func() erfolgen.

Ich werde die diesbezüglich in der C# Sprachspezifikation nachschlagen.

Kabelsalat
2007-10-18, 20:43:49
Ich habe meinen Denkfehler gefunden: Die Initialisierung von Instanzvariablen wird wie angenommen durch einen (notfalls implizit erstellten) Konstruktor übernommen. Der Initialisierungscode wird jedoch vor Ausführung eines anderen Konstruktors - gemäß C# Sprachstandard als "constructor initializer" bezeichnet (Ecma Standard 334 4th Edition, S. 321) - ausgeführt. Für den Code im eigentlichen Konstruktorblock gilt allerdings, dass er erst nach einem etwaigen "constructor initializer" aufgerufen wird. Möglich ist dies, da auf IL-Ebene der direkte Konstruktoraufruf erlaubt ist. Erst wird der Initialisierungscode ausgeführt, dann der "constructor initializer" aufgerufen und schließlich die eigentliche Konstruktorlogik.

Gast
2007-10-18, 20:55:54
Class2..ctor() sollte jedoch erst nach Class1..ctor() und damit auch nach dem Aufruf der Methode Class2.Func() erfolgen.


Genau das wird auch gemacht. Aber b ist schon initialisiert, wenn dein eigentlicher ctor Code anfängt. Im IL Code mag das mit in den ctor kommen, aber dort steht es ganz am Anfang. Also der ctor von Class2 sieht dann in IL als pseudo code so aus:

b = 100
call ctor Class1
Console.WriteLine("Class2")

ScottManDeath
2007-10-18, 22:34:39
In C# stellen die new und override Keywords sicher dass eine spaeter der Basisklasse hinzugefuegten Methode nicht versehentlich Methoden der abgeleiteten Klasse verdeckt usw.

Siehe auch http://msdn2.microsoft.com/en-us/library/aa288479(VS.71).aspx

Gast
2007-10-19, 07:39:27
Peter-Pike Sloan meine, falls du den kennst. Ich durfte mich mal länger mit PRT auseinandersetzen ... war spassig X-D