
Zitat von
Testgrave
Vorallem im zweiten Input (in3), weis ich dass es fuer den TA ca. 1 millionen segmentation faults gab, aber wenn ich es in Linux (Ubuntu) ausfuehre, klappt alles gut. Kein Error und der Output ist auch richtig.
Das ist eigenartig. Wobei "ca. 1 Million segmentation faults" eigentlich nicht möglich ist, ein Programm steigt normalerweise nach der ersten aus. 
Weißt du zufällig, auf welchem System das Programm zwecks Benotung getestet wird und welcher C++-Compiler in welcher Version dort genutzt wird? Vielleicht könntest du das System dann in einer virtuellen Maschine nachbilden (gleiches Betriebssystem, gleiche Compilerversion) und es dort mal testen.
Falls das nicht möglich ist, könntest du hier auch mal den relevanten Codeabschnitt zeigen. Vielleicht ist daran etwas auffällig.

Zitat von
Testgrave
Das werde ich mir aufjedenfall mal anschauen. Wir duerfen C++11 benutzen, also das waere aufjedenfall eine Moeglichkeit. Laeuft das dann wie Garbage Collection in Java? Oder ist das wieder ein anderes Model fuers Speichermanagement?
Nein, das läuft nicht ganz so wie Garbage Collection in Java. std::shared_ptr geht aber in die Richtung: Intern wird in der Struktur zusätzlich zum Pointer ein Referenzzähler genutzt, der zählt, wie viele std::shared_ptr-Objekte noch auf diesen Pointer verweisen. Fällt dieser Zähler auf 0, wird der Zeiger freigegeben. std::unique_ptr gibt den Speicher des zugehörigen Objektes frei, sobald der Gültigkeitsbereich des std::unique_ptr-Objektes verlassen wird:
std::unique_ptr is a smart pointer that retains sole ownership of an object through a pointer and destroys that object when the unique_ptr goes out of scope. No two unique_ptr instances can manage the same object.
The object is destroyed and its memory deallocated when either of the following happens:
- unique_ptr managing the object is destroyed
- unique_ptr managing the object is assigned another pointer via operator= or reset().
Grundidee dahinter ist, dass man anstelle von
Code:
Foo * p1 = new Foo;
einfach
Code:
std::unique_ptr<Foo> p1(new Foo);
verwendet. (Foo sei hier der Name eines Typs bzw. einer Klasse.) Damit besteht nicht die Gefahr, dass man die zugehörige delete-Anweisung zur Speicherfreigabe vergisst, denn darum kümmert sich std::unique_ptr. Zweimal freigeben kann man das Objekt im Pointer dann auch nicht. (Es sei denn, man nutzt std::unique_ptr::release() und verwaltet den Pointer wieder selbst, aber das ist eigentlich nicht der Sinn dieser Klasse.)
Von den beiden Klassen std::unique_ptr und std::shared_ptr sollte man in den meisten Fällen std::unique_ptr nehmen. Es sei denn, man will diesen Pointer an verschiedene Funktionen/Objekte weiterreichen, die auch darauf zugreifen können; dann ist std::shared_ptr angebracht. Vermutlich ist es gut, wenn du dir mal die eher schon verlinkte Seite zu den beiden Pointertypen auf cppreference.com durchliest und dir ein paar der Beispiele anschaust, um die Grundidee zu verstehen.
Aber am sichersten umgeht man segmentation faults durch falschen Umgang mit Pointern, indem man Pointer vermeidet. Codes wie
Code:
int myFunction()
{
Foo * ptr = new Foo; //allocate memory + create object of class Foo
...
//do something with ptr
...
delete ptr; //destroy object + free memory
ptr = nullptr; //to avoid dangling pointer
...
return 1;
}
bergen immer die Gefahr, dass zwischen new und delete irgendetwas eintritt, was verhindert, dass man beim delete ankommt. Das kann beispielsweise eine Exception sein oder (wenn man innerhalb einer Funktion ist) eine return-Anweisung ohne vorheriges delete.
Stattdessen könnte man den Code mit smart pointern umschreiben:
Code:
int myFunction()
{
//allocate memory + create object of class Foo, manage by unique_ptr
std::unique_ptr<Foo> ptr(new Foo);
...
//do something with ptr
...
//no delete required, std::unique_ptr will do that
return 1;
}
Noch einfacher geht's natürlich ohne Pointer, wenn man das Objekt außerhalb der Funktion ohnehin nicht nutzt:
Code:
int myFunction()
{
Foo f1;
...
//do something with f1
...
return 1;
}
Damit hat man gar keinen Pointer mehr und das Objekt f1 wird zerstört, sobald die Funktion verlassen wird.