Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

71

20.05.2016, 10:55

Dass man mit GC-Sprachen auch unangenehmen Situationen begegnet ist mir klar und das braucht ihr mir wirklich nicht erklären. Aus meiner Sicht verringert sich i.d.R. aber die Problemfläche für den gemeinen Programmierer ungemein.

Wir haben also auf der einen Hand eine einzige Art von Resource – nämlich Heapobjekte (≠ Speicher!) – auf der anderen Hand sämtliche anderen Arten von Resource. Der GC managed dir eine, der lächerliche Preis, den du dafür bezahlen musst, ist, dass korrektes Management aller anderen Arten von Resource praktisch unmöglich wird. Ein Geschäft, auf das sich niemand, der Recht bei Sinnen ist, einlassen sollte...
Und doch tun es so viele. Und so wird dabei zum Beispiel argumentiert: http://embedded-computing.com/guest-blog…t-iot-gateways/

Es ist schwer bis unmöglich, zyklische Besitzverhältnisse abzubilden und das ist auch gut so; das ist kein Nachteil, sondern gerade eben ein massiver Vorteil, weil der Compiler dir schon gar nicht erst erlaubt, diesen Fehler zu begehen, insbesondere nicht unabsichtlich. Zyklische Graphen an sich sind dagegen kein Problem...
Wie verwaltet man denn zum Beispiel den Speicher eines Graphen in C++? Ich bin da echt eingerostet. Muss man da nicht immer eine eigene Zyklus-Erkennung einbauen? Solche Graphen erstrecken sich ja dann oft über verschiedene Teile der Anwendung, ohne dass man es überhaupt richtig weiß. Dass man sowas ohne große Probleme in GC-Sprachen handlen kann, ist neben dynamischer Verlinkung mMn auch der Grund, warum man bei Nicht-GC-Sprachen nicht so ein sich rasant entwickelndes Open-Source-Öko-System hat - so zumindest mein Eindruck.

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Chromanoid« (20.05.2016, 11:04)


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

72

20.05.2016, 11:19

Wie verwaltet man denn zum Beispiel den Speicher eines Graphen in C++?

Das würde ich per Adjazenzmatrix oder Adjazenzlisten machen. Zumindest in den meisten Fällen. Aber nicht nur in C++ sondern auch in GC Sprachen. Das worauf du hinaus willst könnte man aber doch lösen indem eine Graphenklasse alle Knoten besitzt und die Knoten selbst kennen dann nur ihre Nachbarn, besitzen diese aber eben nicht. Abbilden könnte man das dann zum Beispiel durch raw-Pointer. Ich mache es zumindest so dass ich Besitz bei Zeigern durch unique_ptr festlege und raw-Pointer dann bei kennt-Beziehungen einsetze.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Helmut

5x Contest-Sieger

Beiträge: 692

Wohnort: Bielefeld

  • Private Nachricht senden

73

20.05.2016, 11:49

Das Ergebnis sind OutOfMemory-Probleme. Solches null-Setzen ist aber an sich auch kein schöner Stil. Nur leider in der Praxis unvermeidbar. Genauso, wie ein GC.collect/flush eben auch in gewissen Situationen unbedingt notwendig ist, so grauenvoll das auch weh tut solchen Code zu sehen oder selbst schreiben zu müssen.
Ich kenne dieses Vorgehen so aus der Praxis nicht.

Die Probleme gibt es aber. Meistens läuft es sogar darauf hinaus, dass man effektiv versucht den GC zu vermeiden. Und dass der Code dann in einer GC basierten Sprache unleserlich wird ist wohl klar.
Minecraft hat z.B. hauptsächlich wegen dem GC massive Performanceprobleme. Und dabei muss man beachten, dass dort der Rendercode schon in C++ ausgelagert ist und man bei dem Spiel auch nicht gerade von guter Grafik reden kann.
(https://www.reddit.com/r/programming/com…ny_performance/)
Sei stets geduldig gegenüber Leuten, die nicht mit dir übereinstimmen. Sie haben ein Recht auf ihren Standpunkt - trotz ihrer lächerlichen Meinung. (F. Hollaender)

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

74

20.05.2016, 11:52

Graphen erstrecken sich ja dann oft über verschiedene Teile der Anwendung, ohne dass man es überhaupt richtig weiß
Dafür gibt es das Prinzip der Ownership. Da kann man wie schon gesagt nicht "ausversehen" einen Zyklus bauen, der eine Freigabe verhindert. unique_ptr und raw ptr sind in C++ dafür ein ideales Mittel der Wahl. Da hast du quasi einen Baum (keinen Graphen!) aus Ownership und non-owned-Referenzen, die das ganze dann zu einem Graphen machen. Es ist nicht möglich da versehentlich einen Zyklus aus Objekt-Ownership zu basteln (wie bei dem Ring-Example schon gezeigt). Wenn du tatsächlich zyklische Ownership in deinem Use-Case hast (und die hat man eigentlich zu 99.99% nicht - ich hatte z.B. noch keinen einzigen Fall, wo das der Fall gewesen wäre), dann kannst du das noch immer über shared_ptr ähnlich lösen wie das ein GC tun würde. Da ist ein GC vermutlich auch eine echt schöne Sache. Aber für die 0.01% der Fälle (von denen ich wie gesagt noch keinen einzigen jemals in der Praxis hatte), möchte ich mir nicht all die Nachteile eines GCs an's Bein binden.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

dot

Supermoderator

  • »dot« ist der Autor dieses Themas

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

75

20.05.2016, 11:56

Wenn du tatsächlich zyklische Ownership in deinem Use-Case hast [...]

Ich würde soweit gehen, zu sagen, dass du in dem Fall deinen Use-Case einfach nicht gut genug verstanden hast und gerade dabei bist, was falsch zu machen... ;)


Wie verwaltet man denn zum Beispiel den Speicher eines Graphen in C++? Ich bin da echt eingerostet. Muss man da nicht immer eine eigene Zyklus-Erkennung einbauen?

Ganz einfach: Der Graph besitzt seine Knoten, die Knoten verlinken sich gegenseitig, fertig. Das vermeintliche Problem entsteht erst, wenn man den Fehler begeht, die Konzepte "Besitz" und "Referenz", die nichts miteinander zu tun haben, zu vermischen...

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »dot« (20.05.2016, 12:02)


76

20.05.2016, 12:05

Das würde ich per Adjazenzmatrix oder Adjazenzlisten machen. Zumindest in den meisten Fällen. Aber nicht nur in C++ sondern auch in GC Sprachen.
Ah, verstehe, stimmt da war was :) Aber wir halten fest, es ist eine besondere Verwaltung nötig, die jetzt nicht unbedingt auf der Hand liegt, wenn man noch nicht einmal weiß, dass man gerade einen Graphen implementiert.

Das worauf du hinaus willst könnte man aber doch lösen indem eine Graphenklasse alle Knoten besitzt und die Knoten selbst kennen dann nur ihre Nachbarn, besitzen diese aber eben nicht. Abbilden könnte man das dann zum Beispiel durch raw-Pointer. Ich mache es zumindest so dass ich Besitz bei Zeigern durch unique_ptr festlege und raw-Pointer dann bei kennt-Beziehungen einsetze.
Naja, das worauf ich hinaus will, sind eher Sachen wie zig Referenzen, die irgendwie zu einem Zyklus führen, ohne dass man überhaupt einen Graphen entwickeln will. Jede Bibliothek, die man benutzt, muss gegen sowas abgesichert sein oder etwa nicht? In GC-Sprachen ist das sehr viel unwahrscheinlicher, dass es da zu Problemen kommt. Ich versuche mal ein Beispiel an den Haaren herbeizuziehen ;), vielleicht problematisiere ich hier auch, aber ich glaube das ist wirklich schnell mal ein Problem:

[ Service A (Bibliothek 1) -nutzt-> Service B (Bibliothek 2) ] Außerhalb der Organisation
[ Service B (Bibliothek 2) -verwaltet-> Objekt X (User Code) ] Aufgabenbereich Team 1
[ Objekt X (User Code) -nutzt-> Service A (Bibliothek 1) ] Aufgabenbereich Team 2

Der Zyklus entsteht hier durch die ungünstige Implementierung von Objekt X. Das ist natürlich nicht sauber entwickelt, aber der Zyklus ist erst mal nicht so einfach nachzuvollziehen, insbesondere wenn Interfaces verwendet werden, die den Zyklus im Code nicht deutlich machen.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

77

20.05.2016, 12:09

Naja, das worauf ich hinaus will, sind eher Sachen wie zig Referenzen, die irgendwie zu einem Zyklus führen, ohne dass man überhaupt einen Graphen entwickeln will.
Das ist in Referenz-Sprachen ein echtes Problem. In C++ ist das z.B. überhaupt gar keins, denn bei sauberer C++ Verwendung, ist das technisch nicht möglich zu implementieren.

Interfaces oder nicht sind hier völlig irrelevant. Du darfst durchaus zyklische Datengraphen haben. Aber du solltest niemals einen Besitz-Zyklus haben. In sauberem C++ kannst Du so einen bei klarem Verstand nicht versehentlich bauen. In Java oder C# ist das natürlich überhaupt kein Problem und da ist der Fehler.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

78

20.05.2016, 12:17

Das man in sehr abstrusen Situationen einen Leak bekommt mag sein, aber das ist in 99,9% der Fälle nicht der Fall. Der GC managed Speicher in großen Anwendungen besser als die Summe der Entwickler.
Ich weiß nicht, über welche Praxis du da redest. Meine Erfahrung sieht da anders aus.
Der Vorteil bei "Crashes" in C# oder Java ist einfach der, dass man sie wesentlich einfacher catchen und behandeln kann als einen Zugriff auf ungültigen Speicher in C++. Das ist so, ja. Das ist zumeist auch die allseits beliebte NullPointer/NullReferenceException, weil jemand zu dumm war einen Optional Value vor Verwendung nicht auf Inhalt zu prüfen. Dafür brauche ich aber nur Managed Memory, ich benötige dafür nicht automatisch auch Garbage Collection. Wahlweise kann ich dafür auch eine Sprache verwenden, die solche Prüfungen unabdingbar macht. Wie eben z.B. Swift oder Rust. Außer man benutzt sie inkorrekt und äußerst dämlich, verhindert schon die Sprache / der Compiler einen Zugriff auf invaliden Speicher oder einen Nullpointer (ja, richtig gelesen, korrekt eingesetztes Swift macht einen Nullpointer-Zugriff unmöglich schon zur Compile-Zeit!). DAS ist z.B. eines der Oberhammer-Dinge, die an Swift richtig geil sind. Und Swift hat weder, noch braucht es, einen GC.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »BlueCobold« (20.05.2016, 12:22)


Nimelrian

Alter Hase

Beiträge: 1 216

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

79

20.05.2016, 12:20

Und dabei muss man beachten, dass dort der Rendercode schon in C++ ausgelagert ist und man bei dem Spiel auch nicht gerade von guter Grafik reden kann.

Quelle? Es wäre mir neu, dass Minecraft das Rendering in C++ abwickelt. Ich rede hier nicht von der eigentlichen OpenGL Implementierung, bzw den lwjgl Libs, sondern von der Renderlogik. Der GC ist in Minecraft so eine Performancebremse, weil man irgendwann mal ziemlich viel vom Datenmodell refactored hat und dabei nicht an die Eigenheiten des GC gedacht hat.
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

dot

Supermoderator

  • »dot« ist der Autor dieses Themas

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

80

20.05.2016, 12:49

Zitat

Doch; und genau das ist ja das Problem. Ein GC verhindert keine Leaks im Allgemeinen. Das einzige, das ein GC vermeidet, ist das Leaken von Heapobjekten (wobei man selbst darüber diskutieren kann). Wir haben also auf der einen Hand eine einzige Art von Resource – nämlich Heapobjekte (≠ Speicher!) – auf der anderen Hand sämtliche anderen Arten von Resource. Der GC managed dir eine, der lächerliche Preis, den du dafür bezahlen musst, ist, dass korrektes Management aller anderen Arten von Resource praktisch unmöglich wird. Ein Geschäft, auf das sich niemand, der Recht bei Sinnen ist, einlassen sollte...


Da muss ich dir aber widersprechen. Warum sind denn die robustesten großen Anwendungen meist GC-managed?

Hast du da ein Beispiel? Ich wüsste nicht, von was du da gerade redest. Ich hab noch keine große managed Anwendung gesehen, bei der mir spontan das Wort "robust" in den Sinn gekommen wär, im Gegenteil...


Das man in sehr abstrusen Situationen einen Leak bekommt mag sein, aber das ist in 99,9% der Fälle nicht der Fall. Der GC managed Speicher in großen Anwendungen besser als die Summe der Entwickler.

Nochmal: Der GC managed nicht Speicher allgemein, der GC managed nur Heapobjekte und sonst nichts. Und genau das ist das Problem...

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »dot« (20.05.2016, 13:00)


Werbeanzeige