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

Teiby

Frischling

  • »Teiby« ist der Autor dieses Themas

Beiträge: 42

Beruf: Ausbildung

  • Private Nachricht senden

1

04.12.2011, 08:32

Speicher freigeben bei Programmende?

Muss man (oder sollte man) den Speicher selbst bei Programmende freigeben mit "delete"? Oder übernimmt das Betriebssystem das automatisch?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

04.12.2011, 09:15

Das Betriebssystem macht das, aber man sollte trotzdem alles freigeben. Speziell System-Ressourcen werden nämlich eventuell nicht aufgeräumt.
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]

Teiby

Frischling

  • »Teiby« ist der Autor dieses Themas

Beiträge: 42

Beruf: Ausbildung

  • Private Nachricht senden

3

04.12.2011, 10:18

Und wie erstellt man diese spezielle Systemressourcen?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

04.12.2011, 10:32

Das ist unterschiedlich. Das können Sockets sein, Dateien, Texturen, Brushes, Device-Contexts, Timer, ...

Einfache Regel: Alles, was Du anforderst, musst Du auch wieder freigeben.
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]

5

04.12.2011, 10:46

Man kann davon ausgehen, dass das Bertiebssystem den Speicher am Ende aufräumt. Ich verließe mich nicht darauf. Es ist einfach guter Stil, die Resourcen, die man anfordert, auch wieder frei zu geben. Im Fall von C++ gibt es genügend Hilfmittel, welche einem die "Merkliste" abnehmen (STL-Container, smart-pointer, ...). Notfalls schreibt man sich einen Wrapper, welcher bei Zerstörung aufräumt.

Selbst in Python (was derzeit meinen Fokus hat) sollte man trotz refcounting einige Dinge berücksichtigen (besonders files seien da erwähnt).

Grüße ... Heiko

PS. BlueCobold schreibt schon wieder schneller.

Zitat

Ich bin nicht der Messias.
Ich sage, du bist es, Herr. Und ich muss es wissen, denn ich bin schon einigen gefolgt.

https://bitbucket.org/bwbg

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

6

04.12.2011, 10:58

Bei modernen Betriebssystemen wird eigentlich schon alles freigegeben, auch Dateien, Events, ...
Aber solltest du mal für den Embedded-Bereich programmieren, dann kann man sich darauf nicht mehr unbedingt verlassen.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

7

04.12.2011, 12:18

Generell sollte man sich darauf imo auf keinen Fall verlassen. Denn das verführt zu Code, der durchzogen ist von Memory-Leaks. Und gegen die kann das Betriebssystem leider nichts tun...

8

04.12.2011, 18:39

Es gibt auch viele Leute, die meine, in einem guten C++ Programm sollte so gut wie keine delete auftauchen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//C
void doStuff()
{
 FILE *File=NULL;
 File=fopen("bla");
 ///Datei operationen:
 fclose(File);

 //other Stuff
}

//C++

void doStuff()
{
 fstream File("bla");
 File<< Data;
 //kein File.close()
 
 //other Stuff
}


Der Destruktor des Filestreams schließt die Datei automatisch, sobald sie nicht mehr benutzt wird (der Scope (also doStuff()) verlassen wird). Ein fclose kann man vergessen, einen Destruktoraufruf nicht. Natürlich kann man jetzt sagen, ein expliziter File.close()
Aufruf wäre schöner, und er würde auch funktionieren und das erwartete tun, aber ratsam ist er trotzdem nicht: Es wäre möglich, dass am Ende nocheinmal etwas mit der Datei gemacht werden soll. Vielleicht hat man die Aufruf vergessen und versuch jetzt in eine geshclossene Datei zu schreiben. Viel schöner ist es, Objekte möglichst lokal zu halten, in etwa so:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
void doStuff()
{
 {//file operation
  fstream File("bla");
  File<< Data;
  //kein File.close()
 }
 
 //other Stuff
}

Die Datei wird so direkt nach dem Schreiben geschlossen und wenn man später versucht, auf das Objekt zuzugreifen, merkt das schon der Compiler - und Compilerfehler sind IMMER(!!) besser als Laufzeitfehler. Und dadurch, dass die Datei bereits im Konstruktor geöffnet wird, ist sie über ihren gesamten Lebenszeitraum hinweg gültig, was ein sehr großer Vorteil ist. Siehe dazu auch:

http://en.wikipedia.org/wiki/Resource_Ac…_Initialization
(oder die kurze, aber duetsche Version: http://de.wikipedia.org/wiki/Ressourcenb…Initialisierung)

Das selbe funktioniert so ziemlich mit allen Ressourcen in C++. Statt Arrays gibt es std::vector, oder eben ein anderer Container, je nach Anwendung. Für einzelne Objekte am Heap gibt es eine ganze Reihe verschiedener Smartpointer, zum Beispiel von boost oder im neuen C++ Standard (und davor in std::tr1, meine ich).

Also: Lass den Compiler deine Ressourcen verwalten (und überlege immer, ob du nicht ein close oder delete vermeiden kannst, durch Einsatz anderer Klassen). Es ist gut und wichtig, zu wissen was im Hintergrund geschieht, aber man sollte ruhig auf einer höheren Ebene Programmieren.
Lieber dumm fragen, als dumm bleiben!

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

9

15.01.2012, 17:31

Es gibt auch viele Leute, die meine, in einem guten C++ Programm sollte so gut wie keine delete auftauchen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//C
void doStuff()
{
 FILE *File=NULL;
 File=fopen("bla");
 ///Datei operationen:
 fclose(File);

 //other Stuff
}

//C++

void doStuff()
{
 fstream File("bla");
 File<< Data;
 //kein File.close()
 
 //other Stuff
}

(...)
Das ist ein schönes Beispiel wie man einen automatischen Destruktoraufruf beim Verlassen einer Funktion zu was benutzen kann. Aber nach Möglichkeit ohne delete auskommen? Man kann probieren es zu minimieren, aber abgesehen von sehr einfachen Programmen wird man oft ohne dynamisch zur Laufzeit allokierten Speicher wohl kaum auskommen!
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

10

15.01.2012, 17:39

Natürlich braucht man den, aber man soll ihn mit Smartpointern benutzen.

Also ein einfacher scoped_ptr ist wohl immer besser, als ein nackter Zeiger (wenn er sich anwenden lässt), aber schon bei shared_ptr's wird die Sache etwas komplizierter und man muss zum Beispiel aufpassen, dass keine Ringe entstehen und so. Da bevorzuge ich es schon des öfteren, mich selbst um alles zu kümmern.

Komplexe Abhängigkeiten zwischen Objekten sind eh eine eklige Sache, für die es wohl keine automatische Lösung gibt. shared_ptr sind schon ganz ok, aber auch die ansich noch mächtigeren Garbage Collectors (bei denen das Ring Problem nicht mehr entsteht) sind kein Allheilmittel. Ich kann mich da an ein Java RTS erinnern, wo zerstörte Gebäude weiterlebten, weil ein Arbeiter noch eine Referenz darauf hatte. Aber wurden nicht mehr auf der Karte angezeigt und konnten nicht mehr angegriffen werden, aber dieser eine Arbeiter konnte dort trotzdem noch Ressourcen produzieren.
Lieber dumm fragen, als dumm bleiben!

Werbeanzeige