Wie oft unterläuft euch ein Memleak?
-
RAII kostet keine Performance. Wenn das Unternehmen ein Framework ohne RAII einsetzt, wechselt man. Wenn man Code ohne RAII vorgesetzt bekommt, schreibt man ihn um. Wenn man selbst Code ohne RAII abliefert, ist man dumm. Ende der Geschichte.
-
knivil schrieb:
und dann schafft man es nichtmal die Anzahl der new/delete ausgeglichen zu halten. Von C++ gut bescherschen kann dann nicht die Rede sein.
Reizendes Statement. Besonders wenn man daran denkt, daß Shade dir einmal mühevoll erklären mußte, wie Exceptions funktionieren, was umso schwerer war, weil du nicht nur nicht zugeben konntest, daß du sie nicht verstanden hattest, sondern zugleich mit erhobener Nase das Dogma "Exceptions sind für Dumme; gute Programmierer benutzen Fehlercodes" zu propagieren beliebtest
Und jetzt tust du so, als könntest du über die Qualifikation anderer urteilen. Deine hiesigen Einlassungen lassen einige Zweifel daran, daß du die Materie überhaupt selbst hinreichend durchdrungen hast.
-
knivil schrieb:
[...] oder ist Performanceschaedlich.
Inwiefern ist RAII deiner Meinung nach denn "Performanceschaedlich"? RAII sollte in der Regel überhaupt keinen Einfluss auf die Performance haben. Wenn doch, dann machst entweder du was falsch oder dein Compiler kann nichtmal die simpelsten Dinge inlinen. In letzterem Fall solltest du, wenn möglich, wohl den Compiler wegwerfen...
Wobei es mir schwerfällt zu glauben, dass du, selbst wenn absolut nichts geinlined würde, tatsächlich durch RAII Performanceprobleme bekommen würdest. Denn den Overhead der Konstruktor und Destruktoraufrufe hast du ja selbst dann rein prinzipiell nur zweimal, nämlich beim Anfordern und Freigeben der Ressource. Und da sollte aber das Anfordern und Freigeben an sich in aller Regel wohl schon wesentlich länger brauchen, sodass der vergleichsweise mikroskopische Overhead wohl kaum auffallen dürfte...
-
1.) Ich weiss wie Exceptions funktioniere. Damals, heute, morgen.
2.) Wann sie Fehlercodes vorzuziehen sind, haengt von vielen Faktoren ab. Einer davon ist persoenliche Einstellung. Die Grenze ist unscharf. RAII "funktioniert" auch ohne Exceptions.
3.) Memory leaks sind keine Einstellungsfrage.
4.) Du legst mir Worte in den Mund.
5.) Mag jeder selbst urteilen, wieviel dein Beitrag mit meiner Person oder mit dem Thema zu tun hat.
6.) Selbstverstaendlich habe ich mich in dieser Zeit nicht veraendert. ...Danke fuer deine Aufmerksamkeit audacia, diese 6 Zeilen Aufmerksamkeit habe ich dir dafuer gewidmet.
@dot: Es koennen immer Faelle konstruiert werden. Manchmal kommt es genau auf diese an. Beispiele gibt es in meiner Firma viele fuer beide Seiten. Manchmal kann der Compiler nicht gewechselt werden, weil er prozessorspezifisch ist. Davon bin ich ebenfalls betroffen. Und fuer die ganzen Idealisten: Ich Muss ein Mix aus "C mit Klassen" und "Hantieren mit rohen Speicher anstatt structs" pflegen. Nein, neuschreiben ist nicht moeglich. Und es macht mir trotzdem Spass.
Als Beispiel: Liste von allen Kameras abholen, is_GetCameraList: http://www.ids-imaging.de/frontend/files/uEyeManuals/Manual_ger/uEye_Handbuch/index.html . Und sowas muss ich benutzen ... .
-
knivil schrieb:
@dot: Es koennen immer Faelle konstruiert werden.
Da wäre ich mal auf ein einziges Beispiel gespannt.
-
Alter Buggy Code der hinten und vorne Probleme macht - klar sowas muss man manchmal warten. Aber da würde ich echt nicht dafür argumentieren.
Denn da stecken sicher Fehler drin. Auch wenn sie mittlerweile keine große Auswirkung mehr haben
Sobald man aber zB die Plattform wechselt oder Compiler oder so, dann explodiert sicher ein großer Teil...
Das würde ich jetzt nicht wirklich als Argument gegen RAII oder Exceptions sehen - manchmal muss man in den sauren Apfel beißen und solchen dreckscode warten/schreiben.
-
knivil schrieb:
Als Beispiel: Liste von allen Kameras abholen, is_GetCameraList: http://www.ids-imaging.de/frontend/files/uEyeManuals/Manual_ger/uEye_Handbuch/index.html . Und sowas muss ich benutzen ... .
Beispiel für was?
Wenn man möchte kann man hier problemlos RAII verwenden - ist nichtmal viel Aufwand. std::vector<char> bietet sich an, oder im Falle des Falles hab' ich auch schon eigene Hilfsklassen geschrieben alatemplate <class T> struct ArrayGuard { ArrayGuard(T* p = 0) : ptr(p) {} ~ArrayGuard() { delete ptr; } T* ptr; private: ArrayGuard(ArrayGuard const&); ArrayGuard& operator = (ArrayGuard const&); };
Das geht wirklich mit fast jedem Compilern. Und ich mache das sogar wenn ich bestehenden Code warte der kein RAII verwendet. Zumindest wenn ich mehr als 1-2 Zeilen irgendwo ausbessere.
Memory leaks zu erkennen und zu vermeiden muss jeder in C oder C++ koennen, auch wenn sein Vorgaenger kein RAII benutzt hat oder selbst keins verwendet werden kann, beisielsweise gibt das firmeninterne "Framework" nicht her oder ist Performanceschaedlich.
Also die Meinungen darüber was jeder können muss gehen sehr weit auseinander. Wenn du die Summe über alles nimmst, müsste jeder perfekt C++ können, und noch einen gehörigen Batzen Mathematik und theoretische Informatik dazu. Also absolutes Minimum.
Und wer mit new/delete bzw malloc/free nach langer Zeit nicht umgehen kann, sollte eine andere Sprache waehlen, Java beispielsweise. Wo ist das Problem? Alle gleich aufgeschmissen, wenn sie keinen RAII-Code pflegen muessen, von anderen Entwicklern?
Wenn man es nicht verwendet kommt man aus der Übung? Wo ist das Problem? Hältst du uns alle für doof nur weil wir nicht mehr malloc/free verwenden, und daher auch die üblichen Patterns nicht mehr kennen wie man da am besten tut damit man keine Probleme bekommt?
Natürlich könnte ich Code warten wo manuelle Speicherverwaltung verwendet wird. Ich wäre dabei nur (anfangs) ordentlich langsam und hätte (vermutlich dauerhaft) keinen Spass dabei.Ich verstehe auch ehrlich nicht, wo das Problem ist, Memory leaks zu finden.
Das Problem ist nicht Memory-Leaks zu finden (wenn man sie denn reproduzieren kann). Das Problem ist Code zu schreiben der gleich überhaupt keine enthält. Natürlich geht das auch in C, bzw. in "C++ ohne Destruktoren". Es ist nur viel mühsamer, und man muss einige Dinge ganz anders angehen als man sie in "C++ mit Destruktoren" gemacht hätte.
Und nochmal was das finden angeht: hast du Test-Cases mit 100% Branch-Coverage? Wenn nicht, dann wirst du auch mit den besten Tools nicht 100% aller Leaks finden können.
-
knivil schrieb:
RAII "funktioniert" auch ohne Exceptions.
rofl, ne echt? Ich bin dann mal weg, das grenzt ja schon an getrolle.
-
knivil schrieb:
4.) Du legst mir Worte in den Mund.
5.) Mag jeder selbst urteilen, wieviel dein Beitrag mit meiner Person oder mit dem Thema zu tun hat.
6.) Selbstverstaendlich habe ich mich in dieser Zeit nicht veraendert. ...Wenn du ein bißchen weniger arrogant aufträtest, während du fachlich fragwürdige Weisheiten verbreitest, würde es mich auch nicht so in den Fingern jucken. Aber daß du dich verändert hast, sei dir zugestanden; ich sehe ein, daß es nicht besonders nett ist, jemandem vergangene Torheiten vorzuhalten.
knivil schrieb:
Als Beispiel: Liste von allen Kameras abholen, is_GetCameraList: http://www.ids-imaging.de/frontend/files/uEyeManuals/Manual_ger/uEye_Handbuch/index.html . Und sowas muss ich benutzen ... .
Das ist halt eine C-Schnittstelle. Sicher muß man da wissen, wie man mit Fehlercodes eine korrekte Fehlerbehandlung durchführt, wenn man den obligatorischen C++-Wrapper dafür schreibt. Und "die Anzahl der new/delete ausgeglichen zu halten", das ist ja wohl das geringste Problem bei der Fehlerbehandlung; eher verliert man die Übersicht durch die Vielzahl der "Funktionsausgänge", jemand fügt versehentlich ein neues Return-Statement ein und vergißt die damit einhergehenden Obligationen, oder man bedenkt nicht, daß eine der aufgerufenen Funktionen (besonders gemein: Callback-Funktionen) eine Exception werfen kann usw. Kurzum, nach meiner Erfahrung ist Code, der auf Exceptions verzichtet und trotzdem Fehlerbehandlung richtig macht, die absolute Ausnahme. Meistens leakt das Programm nur im erwarteten Fall nicht, und alle oder die meisten anderen Abzweige lassen Ressourcen übrig. Und wie hustbaer feststellt:
hustbaer schrieb:
Und nochmal was das finden angeht: hast du Test-Cases mit 100% Branch-Coverage? Wenn nicht, dann wirst du auch mit den besten Tools nicht 100% aller Leaks finden können.
Ich verstehe jedenfalls nicht, was der Sinngehalt deiner Äußerungen sein soll. Nur echte Männer können Fehlerbehandlung auch ohne RAII? Wer mit Exceptionbehandlung richtig umzugehen weiß, hat sich jedenfalls schonmal Gedanken darüber machen müssen, was im Fehlerfall eigentlich passiert, und ist dadurch schon deutlich begünstigt, wenn du ihn vor dein C mit Klassen setzt. Und sicher gibt es manchmal Fälle, wo man keine Exceptions benutzen kann, weil die Laufzeitumgebung das nicht unterstützt; aber selbst dann nimmt man RAII zu Hilfe und erspart sich manuelle Freigaben, um die obengenannten Probleme einfach systematisch zu umgehen. Kurz, es gibt einfach keinen Grund, neuen Code ohne RAII zu produzieren, wenn dir C++ (mit Destruktoren) zur Verfügung steht.
-
Richtige Memory Leaks haben wir in neurem Code dank RAII keine. Im alten Legacy Code, bzw. Interop Code ab und zu. Mit dem neuren RAII Code haben wir allerdings stellenweise auch Probleme mit dem Speicher, weil Objekte einfach zu lange im Speicher gehalten werden und die Strukturen sehr komplex sind. Also, wenn dann irgendwo Speicherprobleme auftreten, was leider öfter passiert, muss man teilweise schon länger analysieren, wo man Speicher einsparen könnte und Daten früher freigeben, intelligentere MRU Caches schreiben usw. Aber, zum Glück keine richigen Memory Leaks
-
Mechanics schrieb:
weil Objekte einfach zu lange im Speicher gehalten werden
Hm.. interessant. Ich hatte eigentlich noch nie eine Situation, wo das hätte passieren können. Also schon rein vom Konzept her nicht. Insbesondere RAII begünstigt doch eigentlich eine schnelle Freigabe. Könntest du da ein Beispiel nennen?
-
Mechanics schrieb:
Richtige Memory Leaks haben wir in neurem Code dank RAII keine. Im alten Legacy Code, bzw. Interop Code ab und zu. Mit dem neuren RAII Code haben wir allerdings stellenweise auch Probleme mit dem Speicher, weil Objekte einfach zu lange im Speicher gehalten werden und die Strukturen sehr komplex sind.
Das liest sich hier, als wäre RAII eine allumfassende Antwort auf alle Probleme.
Obwohl ich RAII ebenfalls sehr gerne verwende, bleibe ich aber auch den Pointern treu. RAII ist eine sinnvolle Möglichkeit, aber keine Antwort auf alle Probleme, ansonsten hätten Garbage Collections überhaupt keine Diskussionsgrundlage.
Ich bin zwar überhaupt kein Fan von GCs, weil ich liebe fehlerhafte Destruktoren korrigiere als mir gleich ein Monster wie die GC für solche Probleme ins Haus zu holen.
Auch mit RAII darf man den Verstand nicht einfach ausschalten, denn dass sich ''new'' mit RAII komplett ersetzen lässt ist nicht zwangsläufig gegeben.
-
Xin schrieb:
Obwohl ich RAII ebenfalls sehr gerne verwende, bleibe ich aber auch den Pointern treu.
Wieso "obwohl"? Was hat das miteinander zu tun?
Xin schrieb:
Auch mit RAII darf man den Verstand nicht einfach ausschalten, denn dass sich ''new'' mit RAII komplett ersetzen lässt ist nicht zwangsläufig gegeben.
Warum schließen RAII und
new
sich aus?Was willst du eigentlich mit deinem Beitrag sagen?
-
Xin schrieb:
RAII ist eine sinnvolle Möglichkeit, aber keine Antwort auf alle Probleme, ansonsten hätten Garbage Collections überhaupt keine Diskussionsgrundlage.
Tja.. ehm.. du hast da schon irgendwo etwas erkannt.
-
Xin schrieb:
Das liest sich hier, als wäre RAII eine allumfassende Antwort auf alle Probleme.
Das wollte ich damit sagen.
-
@Xin
Zum Programmieren braucht man immer ein Gehirn, und darf es auch nie ausschalten.
RAII ist nur - für mich - wirklich eine einzelne Sache die ungleich mehr bringt als vieles was es sonst noch an "good practices" gibt.Natürlich gibt es auch mit RAII Fälle wo die Dinge anfangen etwas kompliziert zu werden.
Diese Fälle sind aber nach meiner Erfahrung ausreichend selten. Wenn ich hin und wieder gut aufpassen muss was ich mache, ist das für mich kein echtes Problem. Wenn ich dagegen bei jeder Zeile aufpassen muss wie ein Haftelmacher ermüde ich viel zu schnell, und fange dann an Fehler zu machen. Und/oder vergleichsweise sehr sehr langsam zu werden.Und was mein "seit RAII quasi keine Leaks mehr" Statement angeht: das ist einfach ne Beobachtung. Meine Konzentrationsfähigkeit ist heute eher schlechter als noch vor 10 Jahren. Wenn ich trotzdem heute deutlich weniger Leaks produziere als damals, kann es also fast nur daran liegen dass ich heute irgendwas grundsätzlich anderes mache. z.B. andere Patterns/Idioms verwenden.
-
kellerassel: leak mir am arsch
-
Die einzige Existenzberechtigung von GCs ist doch, dass sie unter Umständen schneller sein können. Zb wenn es viele kleine Allocations gibt die aufgeräumt werden müssen, zb in Java.
-
hustbaer schrieb:
@Xin
Zum Programmieren braucht man immer ein Gehirn, und darf es auch nie ausschalten.
RAII ist nur - für mich - wirklich eine einzelne Sache die ungleich mehr bringt als vieles was es sonst noch an "good practices" gibt.Das kann man ohne Zweifel so stehen lassen.
hustbaer schrieb:
Natürlich gibt es auch mit RAII Fälle wo die Dinge anfangen etwas kompliziert zu werden. Diese Fälle sind aber nach meiner Erfahrung ausreichend selten.
Bäume? Listen?
hustbaer schrieb:
Wenn ich hin und wieder gut aufpassen muss was ich mache, ist das für mich kein echtes Problem. Wenn ich dagegen bei jeder Zeile aufpassen muss wie ein Haftelmacher ermüde ich viel zu schnell, und fange dann an Fehler zu machen. Und/oder vergleichsweise sehr sehr langsam zu werden.
Dafür fängt man ggfs. aber an, viel zu kopieren, z.B. wenn man Objekte dann in Vectoren packt.
hustbaer schrieb:
Und was mein "seit RAII quasi keine Leaks mehr" Statement angeht: das ist einfach ne Beobachtung. Meine Konzentrationsfähigkeit ist heute eher schlechter als noch vor 10 Jahren. Wenn ich trotzdem heute deutlich weniger Leaks produziere als damals, kann es also fast nur daran liegen dass ich heute irgendwas grundsätzlich anderes mache. z.B. andere Patterns/Idioms verwenden.
Okay, das ist eine subjektive Erfahrung (die ich zwar in ähnlicher Form teile), aber halt keine Garantie.
--------------
Ethon schrieb:
Die einzige Existenzberechtigung von GCs ist doch, dass sie unter Umständen schneller sein können. Zb wenn es viele kleine Allocations gibt die aufgeräumt werden müssen, zb in Java.
Allocations sind in Java nur dann schneller, wenn man in C++ nicht poolt.
Man hat also durchaus Einfluss auf die Umstände. Beim Freigeben ist C++ dann wieder schneller. Der Umstand ist also auch stark davon abhängig, ob das Programm zwischendurch überhaupt den GC benutzt oder einfach nur solange Speicher verteilt, bis am Ende einfach alles jemals genutzte am Stück freigegeben wird.
Das ist natürlich schnell... aber Speicheraufwendig.
-
Ethon schrieb:
Die einzige Existenzberechtigung von GCs ist doch, dass sie unter Umständen schneller sein können. Zb wenn es viele kleine Allocations gibt die aufgeräumt werden müssen, zb in Java.
Das kannst du in C++ ganz leicht global (Allokationsoperatoren überschreiben), oder lokal (eigene Allokatoren nutzen) kontrollieren. Und das genau abgestimmt auf deine Wünsche. Zudem legt man viele kleine Objekte eher auf dem Stack an (was einem GC weit überlegen ist, viele kleine Objekte sind eigentlich oft das Paradebeispiel für das Versagen von GCs), oder reserviert gleich viel Speicher. Jedenfalls hat man alle Möglichkeiten die ein GC hat, außer Speicher umräumen.