Ein paar Zeilen Code legen einen Mac lahm?

sg-1

Enthusiast
Thread Starter
Mitglied seit
19.12.2007
Beiträge
2.097
zuerst muss ich sagen, dass dieses Thema auch noch im Mac-Forum-Teil existiert - keine Ahnung, wo es besser beantwortet/besucht wird...

Situation:

ich schreibe ein c++ Programm, dass ein Objekt anlegt und dafür Speicher im Heap belegt.
Sinn des Ganzen ist die komplette Belegung des gesamten Arbeitsspeichers und Demonstration, was dann passiert. (also ob das Programm abstürzt, oder wie sich das System sonst verhält)

der Code:
Code:
#include <iostream>

class blub
{
    public:
        double* x;
        blub()
        {
            x = new double;
        }   
        ~blub() {}
};

int main(void){
 	while(1)
 	{       	
     	 blub* haha = new blub();
    }
    return 0;
}

Soweit dazu. Jetzt ist irgendwann der Ran voll und OSX lagert in /var/vm/swapfile aus. Jetzt ist irgendwann die Festplatte voll.

Jetzt zum Problem:
WARUM stürzt das Programm jetzt nicht einfach ab, sondern versucht trotzdem, eine Swapfile anzulegen (bemerkbar am kurzzeitigen Erscheinen einer 0byte Swapfile) - Das System freezed natürlich und es hilft nur ein Neustart.


Mögliche Lösung:
Swapfiles deaktivieren - gesagt getan. OSX legt bei mir keine Swaps mehr an - ABER, jetzt kommt genau der gleiche Mist:
WARUM belegt das System jetzt beim Ausführen meines kleinen Programms in der Konsole den GESAMTEN Ram (8gb) bis auf ein paar KB/MB und schießt das Programm nicht einfach ab, wie z.b. unter Windows?
 
Zuletzt bearbeitet:
Wenn Du diese Anzeige nicht sehen willst, registriere Dich und/oder logge Dich ein.
Ich kann dir nicht sagen, warum der Mac sich so verhält aber ich kann dir Stackoverflow empfehlen für solche Fragen. Die Leute dort wissen wovon sie reden.
Stack Overflow
Werde es später mal auf Linux probieren und gucken, wie es sich da verhält.
 
Zuletzt bearbeitet:
Edit will nochmal:

WARUM belegt das System jetzt beim Ausführen meines kleinen Programms in der Konsole den GESAMTEN Ram (8gb) bis auf ein paar KB/MB und schießt das Programm nicht einfach ab, wie z.b. unter Windows?
Wenn ich das Teil unter Windows kompiliere, verabschiedet sich das Programm schon kurz nach dem es 2GB RAM gefressen hat. Grund dafür ist ne Exception die geworfen wird. Dieses Programm kann gar nicht "einfach abgeschlossen werden", da es eine Endlosschleife ist.
 
Zuletzt bearbeitet:
Warum sollte es den Prozess killen? Eigentlich macht das Prog nix verbotenes und verursacht keine Fehler :)
 
Warum sollte es den Prozess killen? Eigentlich macht das Prog nix verbotenes und verursacht keine Fehler :)

Er allokiert Daten auf dem Heap ohne diese wieder frei zu geben (delete) und das Programm stürzt ab. In seinem Fall eben nicht... bei ihm stürzt der Rechner ab.

Die Frage ist eben ... warum wirft das Programm keine Exception.
 
Zuletzt bearbeitet:
Kommt auf das Betriebssystem an wie das den Speicher Verwaltet. Im Idealfall sollte das Betriebsystem eine Fehlermeldung an das Programm abgeben. Da in der Endlosschleife kein Exceptionhandling ist, wird das unweigerlich zum Absturz des Programmes führen.
 
das ist es ja - unter windows stürzt das programm normal ab, was meiner meinung nach sinn macht. Aber unter OSX stützt nix ab. Das System verhindert nicht die Ausführung der Endlosschleife bzw. Allocation neuen Speichers, sondern lässt das Programm laufen, bis das System abschmiert... darf doch nicht sein..

exceptions sind bewusst nicht drin, weil es abstürzen soll. ich erwarte ja, dass das system meinen prozess abstürzen lässt, aber es läuft so, dass das system lieber abstürzt...
 
Damit hättest du die Frage
Sinn des Ganzen ist die komplette Belegung des gesamten Arbeitsspeichers und Demonstration, was dann passiert. (also ob das Programm abstürzt, oder wie sich das System sonst verhält)
wohl beantwortet? :fresse:
 
ja, die frage ist beantwortet und sollte mir demonstrieren, wie sich osx im vergleich zu windows verhält. auf win wurde es auch getestet und das programm stürzt ab 2gb allocierten speicher ab (als 32bit programm bisher getestet).
Es wirft allerdings eine wesentliche neue Frage auf: Warum verhindert OSX nicht, dass mein Programm ALLE Ressourcen frisst. ich hätte dann doch gerne, dass das Programm abschmiert und mein System weiter läuft...
 
Naja, die Frage ist halt ab wann soll das Betriebssystem eingreifen ?

Stell dir vor du führst ein Speicherintensives Programm aus, welches komplizierte Berechnungen anstellen soll, und dafür kurz 5GB RAM braucht.
Aber das ist ja kein Problem, weil du einen PC mit 8GB gekauft hast.
Und jetzt kommt dein Windows her und macht ab 2GB spontan mal Schluss, obwohl du noch genug Reserve hättest. Wäre das besser ?

Wobei die 2GB mit Sicherheit nicht allg. sind. Versuch es mal als 64bit zu kompillieren, was dann auf Windows passiert. Könnte sein dass es dann genau wie auf dem Mac auch bis (fast) 8GB weiterläuft und dann erst abschmiert.

Aber gut, das BS sollte schon eingreifen bevor (fast) alle Reserven weg sind. Sprich wenn von 8GB vllt nur noch ~10MB frei sind. Spätestens dann wenn ein Absturz / einfrieren des Systems droht.
Warum OSX das nicht tut ? Keine Ahnung.

Aber war das nicht bis Windows XP auch noch so dass sich XP aufgehängt hat ?
Ich glaube dass hat sich erst seit der "Virtualisierung" des Speicher ab Windows Vista geändert.... aber Achtung: nur gefährliches Halbwissen/Erinnerung aus einer älteren Zeitschrift.
 
der installierte compiler ist 4.2
 
So am Rande; ich hab es auf Windows 8 64Bit kompiliert - war ebenfalls bei 2gb Schluss.
 
Die Frage ist doch, warum das Ding unter Windows automatisch abgeschossen wird. Eigentlich macht das keinen Sinn. Warum sollte ein Prozess abgeschossen werden, der Ressourcenhungrig ist?

Ein Webserver wird bei extremer Belastung nicht einfach den Apache abschießen, nur weil der RAM voll ist, sondern seine Webseiten schön weiter ausliefern bis nichts mehr geht. Das ist eine Entscheidung, die in den Händen eines Admins besser aufgehoben ist, als bei einem System.

Ein anderes Beispiel wäre ein Programm, dass zum Start erstmal nen paar Gigabyte an Variablen anlegt um später mit diesen zu rechnen. Wo liegt da der Sinn so etwas zu unterbinden?

Es ist die Aufgabe eines Entwicklers so etwas defensiv zu entwickeln und sich nicht darauf zu verlassen, dass schlechter Code und Memory Leaks durch das System gefixt werden.

In Java gibt es da ganz eindeutige Mechanismen, denn eine VM wird immer nur mit einer bestimmten Menge an RAM geladen. Wenn du mehr brauchst, musst du das beim Start des Prozesses als Argument übergeben.
 
Die Sache mit der Compilerversion zeigt eigentlich, dass das System damit überhaupt nichts zu tun hat. Die Funktion "New" prüft ob Speicher reserviert werden konnte und wirft gegebenenfalls eine Exception. Wieviel Speicher die Anwendung haben darf, ist Aufgabe des Entwicklers. Standard sind 2GB für den Kernel und 2GB für den User. Macht zusammen genau 4GB. Mehr ist mit 32Bit nicht adressierbar. Beim Compilieren könnte man auch 1GB Kernel und 3GB User konfigurieren aber dann mit dem Risiko, dass der Kernel sich verabschiedet noch lange bevor der User seine 3GB belegt hat. Unter 64Bit mit entsprechender Compiler Konfiguration ist mehr Speicher machbar.

Sorry aber ich versteh nicht so richtig wo überhaupt dein Problem ist. Wenn ich eine Datei nur lesend öffne und dann versuche zu schreiben, dann wundere ich mich doch auch nicht über die Exception mit anschließendem Absturz. Du bist der Entwickler. Die Funktion "New" kann eine Exception werfen. Arbeite damit so wie du es wünscht aber suche doch nicht Fehler wo keine sind.
Wenn du willst, dass keine Exception und kein Absturz kommt, dann kannst du die Exception auch unterdrücken. Deine Endlosschleife würde fleißig weiter Speicher reservieren aber dabei immer die gleiche Speicheradresse als Rückgabewert bekommen. Dann hast du scheinbar zusätzliche GB reserviert die aber alle exakt der gleicher Speicheradresse haben. Deine Endlosschleife wird es nicht stören solange du nichts weiter mit dem reservierten Speicher vor hast. Interessant wird es, wenn du dann rechnen möchtest. a:=b+c wird dank der identischen Speicheradressen automatisch zu a:=a+a. Falsche Rechenergebnise und keiner weiß wie sie zustande kommen. Genau diese Gefahr hat man in neueren Compilern mit der Exception ausgeschlossen.

Java und C++ kann man an diesem Punkt nicht vergleichen weil die Philosophi bei der Speicherreservierung eine völlig andere ist.
 
WARUM stürzt das Programm jetzt nicht einfach ab, sondern versucht trotzdem, eine Swapfile anzulegen (bemerkbar am kurzzeitigen Erscheinen einer 0byte Swapfile) - Das System freezed natürlich und es hilft nur ein Neustart.[/B]
Erstens das Programm legt kein Swapfile an, das macht das OS.
Zweitens allozierst Du den Speicher nicht physikalisch sondern nur virtuell -> Stichwort Memory Overcommitment
Drittens kann man den Speicherverbrauch sehr wohl begrenzen, auch den virtuellen. Siehe ulimit
 
... dass informatiker immer so genau sein müssen ;)

wenn ich den virtuellen Speicher mit ulimit -v auf 102400 setze, und dann in der gleichen konsole mein Programm ./aufrufe, dann hab ich keinen unterschied. ...außerdem dachte ich, dass ulimit nur für die aktuelle konsolensitzung gilt?
 
Öhm, ich bin aus Langeweile heute hier drauf gestoßen, just my 2 cents:

Mit dem Code oben holst du dir immer mehr Doubles, und lässt den zugeordneten speicher quasi unadressierbar zurück. Bei objektorientierter Programmierung hast du normalerweise nen Garbage Collector der den Speicher aufräumt, zumindest so theoretisch. Bei C++ ist damit nicht viel her, da muss man das selbst machen. Letztlich ist aber das Betriebssystem für die Speicherverwaltung zuständig...also auch für das Aufräumen ungenutzter Speicherzellen.

MacOS hat halt noch nicht so viele Sicherheitsmechanismen bzw. so eine robuste Speicherverwaltung wie Windows, da haben sich noch nicht so viele Idioten dran ausgelassen dass Apple was tun musste...
 
Bei objektorientierter Programmierung hast du normalerweise nen Garbage Collector der den Speicher aufräumt, zumindest so theoretisch.

Du verwechselst da gerade Destruktor und Garbage Collector. Der Destruktor ist bei Objektorientierung Pflicht. Jedes Objekt hat zumindest den default Destruktor von irgendwo geerbt. Der Garbage Collector ist dagegen eine Funktion von einigen Programmiersprachen aber kein OOP Standard.

Letztlich ist aber das Betriebssystem für die Speicherverwaltung zuständig...also auch für das Aufräumen ungenutzter Speicherzellen.

Du stellst dir das etwas zu einfach vor. Man nehme 2 Objekte, die mit einem Pointer sich gegenseitig Adressieren. Das Betriebssystem kann sich in dem Fall die Karten legen. Es muss davon ausgehen, dass die beiden Objekte noch gebraucht werden. Ein Garbage Collector hat da ein paar ander Tricks. Selbst ein Garbage Collector hat aber seine Grenzen.
 
Stimmt! So weit hab ich nicht gedacht...ich sollte wieder mehr programmieren ;-)
Bei normalem C++ hast du natürlich keine GC, Bei Java dann wieder, aber keine Pointer mit denen du solche Leaks einfachst generieren kannst.

Die Sache ist halt, dass du bei obigem Code auch über den Destruktor wenig ausrichten kannst da du ja nur einen Pointer auf ein Speicherelement hast, d.h. Ne Menge herrenlosen allocated Speicher ...mit dem Destruktor gibst du ja nur das"letzte" Objekt wieder frei.

Um eine definierte Menge speiche zu verbraten würde sich doch eine rekursive Funktion anbieten?
 
Ja, mir ist bekannt was GC und Destruktoren sind. Mir ist auch klar (mittlerweile) warum die kompilierten Zeilen beim ausführen "Speicher fressen" - das os aber trotzdem nicht das programm abstürzen lässt, aber ich wundere mich schon sehr, warum das Apple nicht geregelt hat. Ist doch sonst auch alles durchdacht. Und Speicherverwaltung ist ja wirklich was essentielles bei einem OS.

Gesendet von meinem Galaxy Nexus mit der Hardwareluxx App
 
Zuletzt bearbeitet:
Jetzt geht das geheule schon wieder los. Sorry für die harten Worte aber es wurde doch schon alles gesagt. Apple ist komplett Unschuldig. Lern endlich mit der Funktion New korrekt umzugehen. Lerne richtig zu programmieren. Mache nicht das System für deine Fehler verantwortlich.

Ich bin ja auch kein Freund von Apple aber wenn wir hier schon über Apple herziehen wollen, dann doch nicht so billig und durchschaubar.

Die Sache ist halt, dass du bei obigem Code auch über den Destruktor wenig ausrichten kannst da du ja nur einen Pointer auf ein Speicherelement hast, d.h. Ne Menge herrenlosen allocated Speicher ...mit dem Destruktor gibst du ja nur das"letzte" Objekt wieder frei.

Man müsste den Destruktor natürlich aufrufen bevor man den Pointer auf das nächste Element legt. Genau dafür ist er gedacht.

Um eine definierte Menge speiche zu verbraten würde sich doch eine rekursive Funktion anbieten?

Bei jedem rekursiven Funktionsaufruf muss die Rücksprungadresse im Stacktrace abgelegt werden. Irgendwann ist der Stacktrace einfach voll und das dürfte passieren noch lange bevor der Speicher voll ist. Resultat dürfte eine andere Exception mit Absturz sein.

Was in jedem Falle funktioniert, ist eine einfach oder doppelt verkettete Liste. Minimale CPU Belastung aber maximale Speicherbelegung :d
Bei der verketteten Liste wäre natürlich ein Kontruktor mit Exceptionhandling und Destruktor Pflicht.

Die Disskusion hier ist übrings der Grund warum Java keine Pointer hat. Gibt leider zu viele Programmierer, die damit nicht umgehen können (und dann andere dafür Verantwortlich machen).
 
Zuletzt bearbeitet:
Das sehe ich anders. Wenn man als Programmier will (oder sich zu blöd anstellt) bekommt man jedes System zum Absturz. Gerade mit C++ und Pointern hat man das perfekte Werkzeug dafür.

Das System muss zwar mit den dümmsten Eingaben des Anwenders klar kommen aber bitte nicht auch noch mit den dümmsten Programmierern. Die Lösung im vorliegenden Fall ist so einfach, dass man doch nicht allen ernstes verlangen kann das absichtlich falsch machen zu dürfen und auf das System zu vertrauen.
 
Apple ist zu 100% schuld! Denn man kann ein UNIX auch so implementieren, daß bei so einem falschen Programm, daß das OS nicht abschmiert.

Und wieso ist das Programm "falsch"? Es tut genau das, was der Entwickler vorgesehen hat - nur benötigt es eben..naja sagen wir mal "sehr viel" Speicher ;)
Wie bereits erwähnt wurde: Was wäre wenn du 'ne Software hast, die halt mal eben 5-6GB von deinen 6GB an sich bräuchte um irgendwelche Berechnungen durchzuführen?
Interessant finde ich halt eher einfach die 2GB Grenze, die unter Windows zu einem Absturz führt.
Ist der Einwurf von little_Skunk hierbei vielleicht des Rätsels Lösung?

little_Sunk schrieb:
Bei jedem rekursiven Funktionsaufruf muss die Rücksprungadresse im Stacktrace abgelegt werden. Irgendwann ist der Stacktrace einfach voll und das dürfte passieren noch lange bevor der Speicher voll ist. Resultat dürfte eine andere Exception mit Absturz sein.

Und nur mal so am Rande - OS X bzw. Darwin nutzt große Teile an Code aus dem FreeBSD-Userland. Und FreeBSD würde ich schon als ziemlich rocksolid betrachten…aber Stopp - soll nun keine Diskussion darüber werden.

Das Thema lag nun etwas über einen Monat brach - aber vielleicht ist es ja dennoch für den TE nach wie vor von Interesse :)

-yumyum
 
Es hat "undefined behavior", weil der zurückgelieferte Zeiger nicht überprüft wird. Ein korrektes Program muß den zurückgelieferten Zeiger überprüfen.

Aber nur, wenn man Richtlinien für Softwareentwicklung folgt. Rein formal ist der Code in Ordnung. Hier ging es ja aber um ein Stück Software, welches ja das Verhalten vom OS testen sollte - wohlmöglich in genau dieser Situation.
 
Interessant finde ich halt eher einfach die 2GB Grenze, die unter Windows zu einem Absturz führt.

Das liegt schlichtweg daran, dass das Programm als 32bit Exe kompiliert wurde. Da ist unter Win bei 2gb Schluss :)

EDIT:
Ich hätte vllt auch mal die älteren Beiträge lesen sollen... Mea culpa :d
 
Zuletzt bearbeitet:
Hardwareluxx setzt keine externen Werbe- und Tracking-Cookies ein. Auf unserer Webseite finden Sie nur noch Cookies nach berechtigtem Interesse (Art. 6 Abs. 1 Satz 1 lit. f DSGVO) oder eigene funktionelle Cookies. Durch die Nutzung unserer Webseite erklären Sie sich damit einverstanden, dass wir diese Cookies setzen. Mehr Informationen und Möglichkeiten zur Einstellung unserer Cookies finden Sie in unserer Datenschutzerklärung.


Zurück
Oben Unten refresh