Erstellen Sie ein Speicherleck, ohne Gabelbomben [geschlossen]

54

Ihre Aufgabe ist es, einen Speicherverlust zu erstellen . Dies ist ein Programm, das sehr viel Speicher benötigt, bis der Computer nicht mehr ausreicht und ein wenig ausgetauscht werden muss, um sich selbst vor dem Auslaufen zu schützen. Die einzige Möglichkeit, den Speicher freizugeben, besteht darin, das Programm im Task-Manager zu beenden oder einen Befehlszeilen-Kill taskkill /im yourprogram /f(unter Windows) auszuführen oder den Computer neu zu starten. Das bloße Schließen der App sollte nicht verhindern, dass der Speicher weiterhin überlastet wird.

Regeln:

  1. Gabelbomben jeglicher Art sind verboten. Das bedeutet, dass die berüchtigte Bash- Linie :(){ :|:&};:verboten ist!

  2. Die Anwendung darf nur mit einem Thread ausgeführt werden. Dies impliziert die Regel der Gabelbomben.

  3. Das Programm darf keine anderen Programme ausführen. Das bedeutet, dass Sie nicht einfach so etwas tun können run(memoryfiller.exe). Die einzige Ausnahme hiervon sind Programme, die mit Ihrem Betriebssystem oder Ihrer Sprache gebündelt sind und nicht primär zur Speicherbelegung vorgesehen sind (dh einen anderen Zweck haben). Das heißt, Dinge wie catund ln -ssind erlaubt.

  4. Sie können so viel Speicher belegen, wie Sie möchten. Je mehr desto besser.

  5. Code muss vollständig erklärt werden.

Viel Glück. Dies ist ein Beliebtheitswettbewerb, bei dem der Code mit den meisten Stimmen nach 10 Tagen ab dem fraglichen Datum gewinnt!

George
quelle
8
"Wenn Sie es schließen, wird es immer noch schwer" - Wenn ein Programm eine ausführbare Shell ist (wie die meisten Windows-Versionen von Skriptsprachen-Interpretern), wird das Programm durch Schließen des Fensters beendet.
Mittwoch,
54
Ist das nicht gerecht while(1)malloc(999);?
Türklinke
10
Ich bin mir nicht sicher, ob "Wenn ich es schließe, sollte es immer noch zu einem Hog Memory werden" mit "Die Anwendung darf nur mit einem Thread ausgeführt werden" kompatibel ist. Wenn kein Thread über einen Speicherblock verfügt, kann das Betriebssystem diesen zurücknehmen, oder?
Aebabis
51
Führen Sie Firefox 26 mit ein paar geöffneten Tabs eine halbe Stunde lang aus. Es wird Ihren Computer in die Knie zwingen.
Braden Best
1
@mniip. Das ist der springende Punkt der Herausforderung. Eine schwierige Herausforderung stellen. Und Türklinke. Ich wollte etwas anderes! ;)
George

Antworten:

78

Windows

Die Win32-API ermöglicht es Ihnen, Speicher in anderen Prozessen zuzuweisen und diesen Speicher dann remote zu lesen / schreiben. Dieses Programm verfügt nur über einen Thread, mit dem jeder auf dem System ausgeführte Prozess aufgelistet wird. Anschließend werden in jedem Prozess wiederholt 1-MB-Puffer zugewiesen, bis die Zuordnung fehlschlägt. Wenn ein Vorgang abgeschlossen ist, wird der nächste fortgesetzt. Die Zuweisungen werden nicht freigegeben, wenn das aufrufende Programm beendet ist - nur wenn / wenn jeder Zielprozess beendet ist. Dadurch bleibt eine Windows 7-VM mit 2 GB in etwa 10 Sekunden hängen. Es erfordert die Ausführung als Administrator.

Kompilieren: cl /MD leak.cpp /link psapi.lib

#include <windows.h>
#include <psapi.h>

typedef void (*ProcFunc)(DWORD pid);
#define ALLOC_SIZE 0x100000
LPVOID buf;

void ForEachProcess(ProcFunc f)
{
    DWORD aProcesses[1024], cbNeeded;

    if (!EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded))
        return;

    for (unsigned int i = 0; i < cbNeeded / sizeof(DWORD); i++)
        if (aProcesses[i] != 0)
            f(aProcesses[i]);
}

void RemoteLeak(DWORD pid)
{
    HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid );
    if (hProcess == NULL)
        return;

    for (;;)
    {
        LPVOID ptr = VirtualAllocEx(hProcess, NULL, ALLOC_SIZE, 
                                    MEM_COMMIT, PAGE_READWRITE);
        if (ptr == NULL)
            return;

        WriteProcessMemory(hProcess, ptr, buf, ALLOC_SIZE, NULL);
    }
}

int main(void)
{
    buf = malloc(ALLOC_SIZE);
    if (buf == NULL)
        return 0;

    memset(buf, 0xFF, ALLOC_SIZE);

    ForEachProcess(RemoteLeak);

    return 0;
}
Andrew Medico
quelle
9
Windows ist böse.
Tomsmeding
4
Ich muss heute Nacht herunterfahren. Ich werde es versuchen;)
George
1
"(läuft als normaler Benutzer ohne Administratorrechte" - da Sie sich nicht sicher sind, benötigen Sie SeDebugPrivilege, das standardmäßig nicht im Token des regulären Benutzers enthalten ist
rkosegi 21.03.14
@rkosegi Danke, behoben.
Andrew Medico
14
+1 Das verdient viele upvotes , wie es so weit ist die einzige Antwort, die das ursprüngliche trifft Closing noch es hog Speicher machen soll Anforderung. Sehr kreative Lösung :-)
Daniel
72

Java

import java.util.concurrent.atomic.AtomicInteger;

public class Hydra {
  // Not actually necessary for the leak - keeps track of how many Hydras there are, so we know when they're all gone
  public static AtomicInteger count = new AtomicInteger(0);
  public Hydra() {
    count.incrementAndGet();
  }
  protected void finalize() {
    new Hydra();
    new Hydra();
    count.decrementAndGet();
  }

  public static void main(String[] args) throws InterruptedException {
    new Hydra();
    while (Hydra.count.get() > 0) {
      // Prevent leaks ;-)
      System.gc();
      System.runFinalization();
    } 
  }
}

Erläuterung

Sie können davon ausgehen, dass der Code keine Verweise enthält (außer denen count, die Sie ignorieren können) und daher nicht lecken kann. Der Finalizer erstellt jedoch zwei neue Hydras. Auch wenn es für diese keine Referenzen gibt, bleiben sie bis zum Abschluss hängen. Dies bedeutet, dass das Programm nur während der Garbage Collection Speicherplatz verliert - daher die Aufrufe von System.gc()und System.runFinalization().

James_pic
quelle
7
@TimS. Wo ist dein Gott jetzt?!?
Cruncher
Sind System.gc()und System.runFinalization()notwendig? Das heißt, wird der gc manchmal zufällig ausgeführt, oder müssen Sie entweder etwas Speicher füllen oder gc aufrufen?
Cruncher
4
In einem typischen Programm System.gc()und System.runFinalization()wäre nicht notwendig. Speicherbereinigung würde natürlich aufgrund von Speicherdruck passieren. In dieser Anwendung gibt es jedoch keinen Speicherdruck, bis die Speicherbereinigung gestartet wird. Ich dachte darüber nach, einige künstlich einzuführen (z. B. indem ich mich new Hydra()innerhalb der Schleife bewege ), dachte aber, dass dies schlimmer ist.
James_pic
1
Ja, ich habe nicht viel Aufmerksamkeit auf die Einschränkung "Das Schließen sollte trotzdem die Erinnerung zerstören" gelegt, da es nicht aussagekräftig erschien (abgesehen von netten OS-Hacks wie @ german_guy's). Java startet immer einen Finalisierungsthread, sodass eine Java-Anwendung möglicherweise Regel 2 nicht befolgen kann.
James_pic
1
Auf Unix-Systemen können Sie SIGKILL nicht blockieren (Signal 9), sodass Sie Ihr Programm nicht unaufhaltsam machen können (naja, es sei denn, Sie schaffen es, das Programm in einen Zustand ununterbrochenen Wartens zu versetzen ... also können Sie möglicherweise einen NFS-Server remote töten, dessen Dateien Sie haben Zugang könnte funktionieren ;-))
Celtschk
37

C

Unter Verwendung der Programmiersprache C und getestet mit Linux-Kernel 2.6.32-49-generic und libc-2.11.1.so.

Sie können den Speicher nur freigeben, indem Sie das Programm im Task-Manager beenden oder taskkill / im yourprogram / f verwenden oder den PC neu starten.

Dies wird erreicht, indem alle Signale außer SIGKILL und SIGSTOP blockiert werden.

Wenn Sie es schließen, sollte es immer noch schwer zu merken sein.

Das hat mich wirklich verwirrt ... Das Beenden oder Schließen beider Prozesse führt zum Abbruch des Prozesses und ermöglicht dem Betriebssystem, den vom Prozess zugewiesenen Speicher zurückzugewinnen. Aber dann musste ich denken, dass Sie mit dem Schließen des Terminals oder eines anderen übergeordneten Prozesses, der den Speicherverlust ausführt, möglicherweise das Terminal schließen möchten. Wenn ich das richtig verstanden habe, habe ich dieses Problem gelöst, indem ich alle Signale blockiert habe, die den Prozess in einen Daemon verwandeln, wenn der übergeordnete Prozess beendet wird. Auf diese Weise können Sie das Terminal schließen, in dem der Prozess ausgeführt wird, und es wird weiter ausgeführt, und es tritt ein Speicherverlust auf.

Gabelbomben jeglicher Art sind verboten. Das bedeutet, dass die berüchtigte Bash: () {: |: &} ;: verboten ist!

Der Prozess gibt nicht auf.

Die Anwendung darf nur mit einem Thread ausgeführt werden. Dies impliziert die Regel der Gabelbomben

Es werden keine neuen Threads erzeugt.

Das Programm darf kein anderes Programm ausführen. Das bedeutet, dass Sie nicht einfach so etwas wie "Ausführen" (memoryfiller.exe) ausführen können.

Es werden keine neuen Prozesse erzeugt.

Sie können so viel Speicher belegen, wie Sie möchten. Je mehr desto besser.

So viel das Betriebssystem bieten kann.

Code muss vollständig erklärt werden.

Der Quelle wurden Kommentare hinzugefügt.

Und zum Schluss hier der Code:

#define _GNU_SOURCE

#include <stdio.h>
#include <signal.h>
#include <sys/resource.h>
#include <unistd.h>
#include <stdlib.h>


int main(int argc, char* argv[]) {

    /*
    set the real, effective and set user id to root,
    so that the process can adjust possible limits.
    if the process doesn't have the CAP_SETUID capability, terminate the process.
    */
    if (setresuid(0, 0, 0) == -1) {
        printf("Are you root?!\n");
        return 1;
    }

    /*
    block all signals except for kill and stop.
    this allows to terminate the parent process (most likely a terminal)
    that this process is running in and turn it into a daemon.
    additionally this makes it impossible to terminate the process
    in a normal way and therefore satisfies the requirement that closing
    it should still make it hog memory.
    */
    sigset_t mask;
    sigfillset(&mask);
    sigprocmask(SIG_SETMASK, &mask, NULL);

    /*
    allow the process to acquire a virtually unlimited amount of memory
    and queue a virtually unlimited amount of signals.
    this is to prevent an out of memory error due to a virtual limit for the root user,
    which would prevent the process from leaking any more memory
    and to prevent the process from getting killed due to too many queued
    signals that the process is blocking.
    */
    struct rlimit memory = { RLIM_INFINITY, RLIM_INFINITY },
                  signal = { RLIM_INFINITY, RLIM_INFINITY};
    setrlimit(RLIMIT_AS, &memory);
    setrlimit(RLIMIT_SIGPENDING, &signal);

    /*
    allocate a buffer big enough to store a file name into it
    that is generated from the process' pid.
    if the file can be opened (which should always be the case unless /proc is not mounted)
    the file will be opened and the string -17 followed by a new line written to it.
    this will cause the oom killer to ignore our process and only kill other,
    innocent processes when running out of memory.
    */
    char file_name[20];
    sprintf(file_name, "/proc/%u/oom_adj", getpid());

    FILE* oom_killer_file = fopen(file_name, "w");
    if (oom_killer_file) {
        fprintf(oom_killer_file, "-17\n");
        fclose(oom_killer_file);
    }

    /*
    get the size of virtual memory pages in bytes,
    so the process knows the size of chunks that have to be
    made dirty to force the kernel to map the virtual memory page into RAM.
    */
    long page_size = sysconf(_SC_PAGESIZE);

    // allocate a virtually infinite amount of memory by chunks of a page size.
    while(1) {
        // will overwrite any previous stored address in tmp, leaking that memory.
        char* tmp = (char*) malloc(page_size);
        if (tmp)
            // make the memory page dirty to force the kernel to map it into RAM.
            tmp[0] = 0;
    }

    return 0;
}

Für alle, die daran interessiert sind, was passiert, wenn Sie dieses Programm am Laufen halten: Auf meinem Testsystem mit 2 GB RAM und 4 GB Swap-Speicher dauerte es ungefähr 10 Minuten, um den RAM aufzufüllen und zu tauschen. Der OOM-Killer hat seine Arbeit aufgenommen und drei Minuten später wurden alle Prozesse beendet. Sogar Maus, Tastatur und Display wurden vom System entfernt. /var/log/kern.log zeigt außer den Prozessen, die beendet wurden, keine nützlichen Informationen an.

foobar
quelle
Ich habe die Quelle bearbeitet, damit der OOM-Killer den Prozess ignoriert und stattdessen unschuldige Prozesse beendet, um Speicher freizugeben.
FOBAR
5
Für alle, die daran interessiert sind, was passiert, wenn Sie dieses Programm am Laufen halten: Auf meinem Testsystem mit 2 GB RAM und 4 GB Swap-Speicher dauerte es ungefähr 10 Minuten, um den RAM aufzufüllen und zu tauschen. Der OOM-Killer hat seine Arbeit aufgenommen und drei Minuten später wurden alle Prozesse beendet. Sogar Maus, Tastatur und Display wurden vom System entfernt. /var/log/kern.log zeigt außer den Prozessen, die beendet wurden, keine nützlichen Informationen an.
foobar
Haha, das ist wundervoll! Sie sollten diese Beschreibung in Ihre Antwort einfügen. +1
Türklinke
1
Ich habe nicht abgelehnt, aber es wäre schön, wenn der Code so formatiert werden könnte, dass zum Lesen der Kommentare kein horizontales Scrollen erforderlich ist.
Paŭlo Ebermann
2
+1 für 1) Prozesse, die Eingabe- / Ausgabegeräte übergeben, werden beendet und 2) ein Programm erstellt, das in den Protokollen nur schwer zu verfolgen ist. Dies ist das Übel, das den Schnurrbart kräuselt.
Kevin - Reinstate Monica
29

Pure Bash

Keine Gabelbombe, das verspreche ich:

:(){ : $@$@;};: :

Es sieht einer Gabelbombe sehr ähnlich und verwendet eine ähnliche rekursive Technik, jedoch keine Gabeln. Natürlich führt dies dazu, dass Ihre Shell nicht mehr genügend Speicher hat. Es wird daher empfohlen, vor dem Einfügen dieses Befehls eine neue Shell zu starten.

  • Definieren Sie eine aufgerufene Funktion :
  • Die Funktion ruft sich einfach rekursiv mit $@(arg list) double auf
  • Nach der Funktionsdefinition wird die :Funktion mit einem Anfangsargument aufgerufen:

Ausgabe:

$ bash
$ :(){ : $1$1;};: :
bash: xmalloc: ../bash/stringlib.c:135: cannot allocate 536870913 bytes (5368795136 bytes allocated)
$

In einer früheren Bearbeitung dieser Antwort habe a=$(yes)ich die Regel "Das Programm darf kein anderes Programm ausführen" beachtet, daher muss ich bashstattdessen pure verwenden, ohne coreutils oder irgendetwas anderes aufzurufen.


Hier ist ein anderes:

BITTE LAUFEN SIE DAS NICHT AUF EINER PRODUKTIONSMASCHINE

:(){ : <(:);};:

Auch dies ist keine Gabelbombe - alles wird innerhalb eines Threads ausgeführt. Dieser scheint meine Ubuntu-VM recht handlich in die Knie zu zwingen, mit wenig Raum für die Wiederherstellung, außer für einen Neustart.

Wie bei der klassischen Gabelbombe wird eine rekursive Funktion :()definiert. Es leitet jedoch keine Anrufe an sich selbst weiter. Stattdessen ruft es sich mit einem Argument auf, das selbst in einer Prozessersetzung aufgerufen wird . Da die Prozessersetzung durch Öffnen eines Dateideskriptors funktioniert /dev/fd/n, wird dadurch nicht nur der Prozessspeicher (Bash), sondern auch der Kernelspeicher aufgebraucht. Auf meinem Ubuntu-Rechner führt dies dazu, dass der Fenstermanager nach ein paar Sekunden und kurz nach dem Beenden dieses Bildschirms nicht mehr funktionsfähig ist:

Bildbeschreibung hier eingeben

Wenn Sie auf klicken, OKwird der folgende Bildschirm angezeigt:

Bildbeschreibung hier eingeben

Keine dieser Optionen scheint eine große Hilfe zu sein - an diesem Punkt scheint ein Neustart die einzig gute Option zu sein.

Digitales Trauma
quelle
3
$ which yes->/usr/bin/yes
Izkata
2
"Die einzige Möglichkeit, den Speicher freizugeben, besteht darin, das Programm im Task-Manager zu beenden oder taskkill / im yourprogram / f zu verwenden oder sogar den PC neu zu starten. Wenn Sie es schließen, wird der Speicher immer noch voll." >> Die Bash kann mit einem SIGTERM beendet werden, so dass es nicht erforderlich ist, sie zu töten, damit sie nicht mehr ausgeführt wird. Außerdem wird die Ausführung angehalten, wenn das System keinen Speicher mehr hat. Sobald die Bash beendet wurde, entweder durch SIGTERM oder wenn der Speicher voll ist, wird der Speicher an das Betriebssystem zurückgegeben.
foobar
Das funktioniert bei mir nicht ... irgendwie ... Ich kann sehen, dass die Erinnerung allmählich verschwindet, aber dies geschieht sehr langsam, und es kann auch durch einfaches Drücken von Strg + C beendet werden. Es läuft jetzt für 1 Minute und es ist etwa 1 GB belegt. Ich habe eine SEHR schnelle Maschine ... aber das sollte doch egal sein, oder?
Stefanos Kalantzis
Auf meinen eigenen Kommentar antworten: Der Befehl hat die Bash tatsächlich nach ca. 2 Minuten und 49 Sekunden beendet. Ich bin ursprünglich davon ausgegangen, dass es aufgrund dieser Antwort sofort losgeht.
Stefanos Kalantzis
@StefanosKalantzis Vielen Dank für Ihre Kommentare. Ich musste ein bisschen mehr nachdenken und fand gerade ein noch böseres Shell-Snippet - siehe Bearbeiten.
Digital Trauma
24

XML

<!DOCTYPE boom [
<!ENTITY Z 'ka-boom!'><!ENTITY Y '&Z;&Z;'><!ENTITY X '&Y;&Y;'><!ENTITY W '&X;&X;'>
<!ENTITY V '&W;&W;'><!ENTITY U '&V;&V;'><!ENTITY T '&U;&U;'><!ENTITY S '&T;&T;'>
<!ENTITY R '&S;&S;'><!ENTITY Q '&R;&R;'><!ENTITY P '&Q;&Q;'><!ENTITY O '&P;&P;'>
<!ENTITY N '&O;&O;'><!ENTITY M '&N;&N;'><!ENTITY L '&M;&M;'><!ENTITY K '&L;&L;'>
<!ENTITY J '&K;&K;'><!ENTITY I '&J;&J;'><!ENTITY H '&I;&I;'><!ENTITY G '&H;&H;'>
<!ENTITY F '&G;&G;'><!ENTITY E '&F;&F;'><!ENTITY D '&E;&E;'><!ENTITY C '&D;&D;'>
<!ENTITY B '&C;&C;'><!ENTITY A '&B;&B;'><!ENTITY z '&A;&A;'><!ENTITY y '&z;&z;'>
<!ENTITY x '&y;&y;'><!ENTITY w '&x;&x;'><!ENTITY v '&w;&w;'><!ENTITY u '&v;&v;'>
<!ENTITY t '&u;&u;'><!ENTITY s '&t;&t;'><!ENTITY r '&s;&s;'><!ENTITY q '&r;&r;'>
<!ENTITY p '&q;&q;'><!ENTITY o '&p;&p;'><!ENTITY n '&o;&o;'><!ENTITY m '&n;&n;'>
<!ENTITY l '&m;&m;'><!ENTITY k '&l;&l;'><!ENTITY j '&k;&k;'><!ENTITY i '&j;&j;'>
<!ENTITY h '&i;&i;'><!ENTITY g '&h;&h;'><!ENTITY f '&g;&g;'><!ENTITY e '&f;&f;'>
<!ENTITY d '&e;&e;'><!ENTITY c '&d;&d;'><!ENTITY b '&c;&c;'><!ENTITY a '&b;&b;'>
]>
<boom a="&a;"/>

Übergeben Sie das Dokument dann an einen XML-Parser, der keine Entitätsreferenzschleifen- / Rekursionserkennung durchführt. Zum Beispiel xpathin Perl enthalten:

xpath boom.xml /

Wie es funktioniert:

  1. Der Parser trifft <boom a="&a;">
  2. Der Parser erweitert "&a;"in"&b;&b;"
  3. Der Parser erweitert eines der "&b;"In "&c;&c;"(bei der Rückkehr wird das andere erweitert "&b;")
  4. Der Parser erweitert eines der "&c;"etc ...

Wenn die volle Ausdehnung eintreten könnte, würde sich "ka-boom!" Unter der Annahme von 2 Bytes pro Zeichen wird versucht, 64 PiB zu verwenden. Die Erweiterung geht "Ka-Boom!" Sie können also normalerweise beobachten, wie der gesamte Speicherplatz in Anspruch genommen wird.

Dies geschieht unter verschiedenen Namen, eine gute Übersicht finden Sie hier: http://projects.webappsec.org/w/page/13247002/XML%20Entity%20Expansion

ɲeuroburɳ
quelle
3
Im Wesentlichen eine Kopie von Billion lacht
Cole Johnson
@ColeJohnson Yup das ist es! Ich habe zum WASC Threat Classification-Projekt beigetragen, daher fühlte ich mich verpflichtet, eher auf WASC als auf Wikipedia zu verweisen. :)
ɲeuroburɳ
22

C ++

int main()
{
    for(;;)int *a=new int;
}

Dieser Code war unerwartet! Es hat meinen Computer aufgehängt, während der Task-Manager geöffnet war, und es hat gezeigt, dass es 890 MB Speicher in 1 Sekunde in Anspruch nahm, und dann hat es auch aufgehängt. Ich weiß nicht, wie das funktioniert, vielleicht gibt es einer Variablen weiterhin Speicherplatz. Um mehr von diesem Code zu erfahren, habe ich eine Anweisung hinzugefügt, delete a;und beim Testen war alles in Ordnung (kein Hängen) gegeben (aufgrund new int) und dann zurück (aufgrund delete a) auf den freien Speicherplatz im neuen Code unten.

int main()
{
    for(;;)
    {
         int *a=new int;
         delete a;
    }
}  

Daraus schließe ich, dass KEIN RAM IN DIESER WELT DIESEN CODE BEHANDELN KANN !!!

BEARBEITEN : Aber viele Prozessoren können zB intel core 2 duonicht mit diesem Code umgehen aber
intel core i-serieskönnen (hat bei mir geklappt ...)

Denken Sie daran, dass die Antwort auf die Frage der erste Code ist, der zweite dient der Erklärung.

Mukul Kumar
quelle
9
Gut, der Compiler glaubt new int, dass Sie den Zeiger immer noch verwenden werden , obwohl Sie ihn überschrieben haben, sodass Sie nie wieder darauf zugreifen können. Es wird also keine Speicherbereinigung aufgerufen, und Sie füllen den Speicher schneller auf, als ein dickes Kind Kegel frisst
David Wilkins
37
@DavidWilkins: ... das ist C ++, C ++ hat keinen Garbage Collector.
Phoshi
32
Wenn es für Sie unerwartet ist, dass dieser Code leckt, sollten Sie C ++ meines Erachtens erst verwenden, wenn Sie es besser gelernt haben.
Svick
1
@svick Aber es ist auch nicht so, als würde man bei Dunkelheit auf eine Dartscheibe schlagen! Ich hatte eine Idee, dass dies die Jobfrage erfüllen wird.
Mukul Kumar
15
@svick Wie zum Teufel soll er 'es besser lernen', wenn er 'C ++ nicht benutzen soll'?
Kevin
16

BrainFuck

+[>+]

Erläuterung:

Um in die Schleife zu gelangen, wird die Zelle auf 1 erhöht. Sie bewegt sich zur nächsten Zelle und erhöht diese auf 1, solange die letzte Zelle positiv war.

Normalerweise weist ein BrainFuck-Interpreter einen Fehler auf, da die Anzahl der Zellen auf dem Band stark begrenzt ist, aber einige Interpreter fügen Zellen dynamisch hinzu. Diese verbrauchen so lange Speicher, bis sie nicht mehr benötigt werden.

beefist ein solcher Interpreter, der im Ubuntu Software Center verfügbar ist. Mein aktueller Lauf auf einem unbenutzten Computer wurde vor 29 Stunden gestartet und hat in dieser Zeit 1 GB RAM verbraucht. Hier ist die Ausgabe vontop

PID  USER        PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND  
2978 sylwester   20   0 1030m 984m 2536 R 100,1 12,4   1750:52 beef

Es hat 4 GB Cache und 6 GB Swap, also werde ich diese Antwort wahrscheinlich mit dem Stand der Dinge in 12 Tagen aktualisieren.

UPDATE 03.24 17:11

PID  USER        PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND  
2978 sylwester   20   0 1868m 1,8g 2456 R  99,9 22,9   6008:18 beef    

UPDATE 03.31 00:20

PID  USER        PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND  
2978 sylwester   20   0 2924m 2,8g 2052 R 100,0 36,1  15019:46 beef   

Es läuft also schon seit 10 Tagen. Es sieht so aus, als würde es noch mindestens 10 Stunden laufen, bevor etwas Interessantes passiert.

Sylwester
quelle
Schön und kurz.
Nrubin29
15

C und POSIX

Hier strebe ich eine hoch portable Lösung an. Das Problem ist, dass Pure C dem Betriebssystem nicht mitzuteilen scheint, dass der Speicher nach dem Schließen des Programms reserviert bleiben soll. Also erlaube ich mir, POSIX zu benutzen; Die meisten Betriebssysteme haben einen gewissen Anspruch auf POSIX-Kompatibilität, einschließlich Windows, Linux und MacOS X. Ich habe es jedoch nur auf Ubuntu 12.04 32bit getestet. Es sind keine Superuser-Berechtigungen erforderlich.

Diese Lösung ist im Wesentlichen die traditionelle while(1){malloc(1);}Lösung. Anstelle von malloc werden jedoch die POSIX-Shared-Memory-Funktionen verwendet. Da jeder Zuordnung ein gemeinsamer Speicherbezeichner zugewiesen wird, kann auch nach Beendigung des Vorgangs auf den Speicher zugegriffen werden. Somit kann der Kernel den Speicher nicht freigeben.

#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>

#define SHMSZ (2*1024*1024) /*Ubuntu rejects shared allocations larger than about 2MiB*/

main() {
  int shmid;
  key_t key = 0xF111; /* Lets use `Fill' as our first ID.*/
  char *shm;

  while(1) { /* Like malloc, but using shared memory */
    if ((shmid = shmget(key, SHMSZ, IPC_CREAT|0666)) < 0){return 1;}/*Get shared memory*/
    if ((shm = shmat(shmid, NULL, 0)) == (void *) -1) { return 1; } /*Attach it        */
    memset(shm,0,SHMSZ);                                            /*Fill it up       */
    key++                                                           /*On to the next ID*/
  }
}
gmatht
quelle
Beste und brillanteste Antwort C IMO. +1
syb0rg
1
Schön. Die erste Lösung, die ich mir ausgedacht habe, war die von Andrew Medico, aber da dies unter Linux nicht möglich ist und ich keine Windows-Programmierung mag, wollte ich durch den gemeinsamen Speicher lecken, konnte mich aber nicht an die POSIX-Funktionsnamen erinnern. Vielen Dank für mich von ihnen zu erinnern;) Alles fand ich war nur mmap Sachen , die auf Prozessbeendigung ... unmapped ist
foobar
14

C #

Das Abbestellen von Ereignissen, bevor der Handler den Gültigkeitsbereich verlässt, führt zu einem Speicherverlust in .NET, bis OutOfMemoryException ausgelöst wird.

using System;

class A
{
    public event Action Event;
}

class B
{
    public void Handler() { }
}

class Program
{
    static void Main()
    {
        A a = new A();

        while( true )
            a.Event += new B().Handler;
    }
}

Erläuterung : In der whileSchleife erstellen wir ein neues Objekt, wodurch das Framework mehr Speicher Bzuweist. Wir verhindern jedoch auch, dass die neue Instanz freigegeben wird, wenn sie den Gültigkeitsbereich verlässt, indem wir einem Ereignis in einer anderen Klasse eine Instanzmethode zuweisen. Dies hat zur Folge, dass die neue Instanz von Bin unserem Code nicht mehr erreichbar ist, aber immer noch eine Referenz vorhanden ist, was bedeutet, dass der GC sie erst freigibt, wenn sie aebenfalls nicht mehr gültig ist.

Bei statischen Ereignissen besteht die gleiche Gefahr, da sie den Gültigkeitsbereich nie verlassen. Sie werden nur dann bereinigt, wenn der Prozess beendet wird, es sei denn, Sie haben sich zuerst vom Ereignis abgemeldet. Speichern Sie immer Ihre Referenzen, Leute!

using System;

class Program
{
    static event Action Event;

    static void Main()
    {
        while( true )
            Event += new Action( delegate{ } );
    }
}

Das Obige funktioniert auf der gleichen Idee: Der Handler ist nicht mehr erreichbar, sobald die whileSchleife den Gültigkeitsbereich verlässt, sodass das Abbestellen des Ereignisses nicht mehr möglich ist. Dies bedeutet, dass der Speicher dort verbleibt, bis das Programm beendet wird. Statische Ereignisse sind wahrscheinlich gefährlicher als Instanzereignisse, da Sie sicherstellen können, dass sie niemals den Gültigkeitsbereich verlassen.

BEARBEITEN : Sie können dasselbe auch mit praktisch jedem anderen Objekt tun, solange Sie eine Referenz hinzufügen und gleichzeitig sicherstellen, dass es keine Möglichkeit gibt, diese Referenz freizugeben.

In diesem Beispiel werden statische Objekte und Arrays verwendet.

using System;
using System.Collections.Generic;

static class Leak
{
    private static List<decimal[]> Junk;

    static Leak()
    {
        Junk = new List<decimal[]>();
    }

    public static void Add( uint size )
    {
        decimal[] arr = new decimal[size];
        Junk.Add( arr );
    }
}

class Program
{
    static void Main()
    {
        while( true )
            Leak.Add( 1 );
    }
}

Arrays werden weiterhin zur Liste hinzugefügt, aber es gibt keine Möglichkeit, die Liste zu löschen, ohne den Code zu ändern, was für Closed-Source-Anwendungen unmöglich wäre. Leak.AddWenn Sie die Zahl erhöhen, an die übergeben wird, wird das Leck schneller ausgelöst. Wenn Sie sie hoch genug einstellen, wird lediglich eine sofortige OverflowException ausgelöst.

Tony Ellis
quelle
10

Bash (keine externen Dienstprogramme)

Keine Gabelbombe hier.

Warnung: Es könnte Ihre Muschel töten.

Ich versuche nur, ein Array von Ganzzahlen zu Referenzzwecken zu erstellen, da ich immer wieder vergesse, wie Ganzzahlen aussehen.

while :; do _+=( $((++__)) ); done

Ergebnisse in:

xmalloc: expr.c:264: cannot allocate 88 bytes (268384240 bytes allocated)
devnull
quelle
2
+1 für "weil ich immer wieder vergesse, wie ganze Zahlen aussehen" :)
David Conrad
8

J (7)

WARNUNG: Dies hat mein System eingefroren, als ich es ausprobiert habe (Windows 8, J 8.01 im qt-Terminal).

2#^:_[_
  • 2# verdoppelt die Länge des Arguments durch Duplizieren jedes Elements,
  • ^:_ Findet den Fixpunkt der gegebenen Funktion (aber es gibt keinen, so dass es endlose Schleifen gibt),
  • [_nennt es mit _als Argument.
Marinus
quelle
8

Haskell (Grahams Nummer)

Es ist sehr einfach: Dies berechnet die Grahamsche Zahl

Im Gegensatz zu anderen Beispielen wird es nicht für immer laufen ... es wird eine Menge CPU verbrauchen, aber theoretisch könnte es enden. wenn es nicht die Tatsache wäre, dass die Nummer zu speichern ...

Das beobachtbare Universum ist viel zu klein, um eine gewöhnliche digitale Darstellung von Grahams Zahl zu enthalten, vorausgesetzt, jede Ziffer belegt ein Planck-Volumen .

(laut Wikipedia)

import Data.Sequence
import Data.Foldable

(↑) a 1 b = a ^ b
(↑) a _ 0 = 1
(↑) a i b = a ↑ (i-1) $ a ↑ i $ b-1

graham = last $ toList $ iterateN 64 (\i -> 3 ↑ i $ 3) 4
main = print graham

Die Idee ist also, dass der Speicher von einer (Reihe von zunehmend) enormen Integer(Haskell's Integer sind von beliebiger Größe) genutzt wird.

Wenn Sie es ausprobieren möchten, müssen Sie möglicherweise die Stapelgröße erhöhen oder es einlegen ghci.

berdario
quelle
2
Dummes Universum, das nicht dem Haskell-Standard für Ganzzahlen entspricht. Warum kann es keine beliebige Größe unterstützen?
PyRulez
6

Inspiriert von @comintern.

Ersetzt / dev / null. Sneaky-Modus aktivieren. Benötigt Kernel-Header, Superuser-Modus und einen funktionierenden Compiler.

# make
# rm /dev/null
# insmod devnull.ko
# chmod go+rw /dev/null

Habe Spaß.

Makefile:

MODULE := devnull
KVERS  ?= $(shell uname -r)
KDIR   ?= /lib/modules/$(KVERS)/build
KMAKE := make -C $(KDIR) M=$(PWD)

obj-m += $(MODULE).o

all:
    $(KMAKE) modules

install:
    $(KMAKE) modules_install

clean:
    $(KMAKE) clean

Quellcode:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/version.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/uaccess.h>

#define DEVICE_NAME "null"
#define MAJOR_NUMBER 0

MODULE_LICENSE("GPL");
MODULE_AUTHOR("nola <[email protected]>");
MODULE_DESCRIPTION("/dev/null - memory leak style");
MODULE_VERSION("0.1");
MODULE_SUPPORTED_DEVICE("null");

static struct class *class_null;
static int major = 0;

static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
static loff_t device_llseek(struct file *, loff_t, int);

static struct file_operations fops = {
    .owner = THIS_MODULE,
    .llseek = &device_llseek,
    .read = &device_read,
    .write = &device_write,
    .open = &device_open,
    .release = &device_release
};

static int __init mod_init(void)
{
    struct device *dev_null;

    if ((major = register_chrdev(MAJOR_NUMBER, DEVICE_NAME, &fops)) < 0) {
        return major;
    }

    /* create /dev/null
     * We use udev to make the file.
     */
    class_null = class_create(THIS_MODULE, DEVICE_NAME);
    if (IS_ERR(class_null)) {
        unregister_chrdev(major, DEVICE_NAME);
        return -EIO;
    }

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
    dev_null = device_create(class_null, NULL, MKDEV(major, 0),
                             NULL, "%s", DEVICE_NAME
        );
#else
    dev_null = device_create(class_null, NULL, MKDEV(major, 0),
                             "%s", DEVICE_NAME
        );
#endif
    if (IS_ERR(dev_null)) {
        class_destroy(class_null);
        unregister_chrdev(major, DEVICE_NAME);
        return -EIO;
    }

    return 0;
}

static void __exit mod_exit(void)
{
    device_destroy(class_null, MKDEV(major, 0));
    class_unregister(class_null);
    class_destroy(class_null);
    unregister_chrdev(major, DEVICE_NAME);
}

static int device_open(struct inode *inode, struct file *file)
{
    file->f_pos = 0x00;

    try_module_get(THIS_MODULE);
    return 0;
}

static int device_release(struct inode *inode, struct file *file)
{
    /* decrement usage count: Not. Uncomment the line for less fun. */
    /* module_put(THIS_MODULE); */
    return 0;
}

static loff_t device_llseek(struct file *filep, loff_t offs, int mode)
{
    loff_t newpos;

    switch (mode) {
    case 2:
    case 0:
        newpos = offs;
        break;

    case 1:
        newpos = filep->f_pos + offs;
        break;

    default:
        return -EINVAL;
    }

    if (newpos < 0) {
        return -EINVAL;
    }

    filep->f_pos = newpos;

    return newpos;
}

static ssize_t device_read(struct file *filep, char *dst, size_t len,
                           loff_t *off)
{
    char *buf = NULL;

    if (dst == NULL || len == 0) {
        return -EINVAL;
    }

    buf = kmalloc(sizeof(char) * len, GFP_KERNEL);
    if (buf == NULL) {
        return -EINVAL;
    }

    /* Do how a /dev/null does.
     */
    memset(dst, 0, len);

    *off += len;
    return len;
}

static ssize_t device_write(struct file *filep, const char *src, size_t len,
                            loff_t *off)
{
    char *buf = NULL;

    buf = kmalloc(sizeof(char) * len, GFP_KERNEL);
    if (buf == NULL) {
        return -EINVAL;
    }

    *off += len;
    return len;
}

module_init(mod_init);
module_exit(mod_exit);

Achtung, dies kann einen Neustart erzwingen!

Es zu entfernen:

# rmmod -f devnull # or a reboot
# rm -rf /dev/null
# mknod /dev/null c 1 3
# chmod go+rw /dev/null
n0la
quelle
6

Rubin

Jeder kennt diese Summe (1 / n ^ 2) = pi ^ 2/6

So kann ich eine Approximationsfunktion definieren:

pi_approx = lambda {|i|
Math.sqrt( 
  6*( 
    (1...Float::INFINITY).map{|n| n.to_f**(-2)}.take(i).reduce(:+)
    )
  )
}

p pi_approx.(100_000)

Natürlich läuft die (1..infinity) wild.

Beachten Sie jedoch, dass die Verwendung von Lazy diese Arbeit machen würde;)

pi_approx = lambda {|i|
Math.sqrt( 
  6*( 
    (1...Float::INFINITY).lazy.map{|n| n.to_f**(-2)}.take(i).reduce(:+)
    )
  )
}

p pi_approx.(100_000)
#=> 3.141583104326456
aherve
quelle
5

C - 28 25 Zeichen (Vollprogramm)

Führen Sie das nicht aus, sonst wird Ihr System schnell eingefroren!

main(){while(malloc(9));}

Der Aufruf von malloc reserviert 9 Byte Speicher und fordert regelmäßig neue Speicherseiten vom Betriebssystem an. Der von malloc zugewiesene Speicher wird sofort gelöscht, da kein Zeiger auf die zurückgegebene Adresse gespeichert wird. Sobald dem System der Arbeitsspeicher (RAM und Auslagerungsspeicher) ausgeht oder das Speicherlimit für den Prozess erreicht ist, bricht das Programm die while-Schleife ab und wird beendet.

Mathieu Rodic
quelle
2
Nicht lange - jedes moderne System sollte einen OOM-Killer haben , der den Prozess einleitet und abbricht . Zumindest Ubuntu 12.04.
Digital Trauma
1
Nun, ich habe mein Ubuntu 13.10 abgestürzt, als ich diesen Code ausprobiert habe ...
Mathieu Rodic
@DigitalTrauma Hat zB FreeBSD eine OOMK?
Ruslan
1
main(){while(malloc(9));}Speichert weitere 3 Zeichen und füllt mein Gedächtnis so ziemlich augenblicklich.
24.
@gmatht: danke für den vorschlag! Ich habe die Antwort bearbeitet ... obwohl mir die Idee gefallen hat, den Block in jeder Schleife zu vergrößern.
Mathieu Rodic
4

VBScript

do
    Set d1 = createobject("Scripting.Dictionary")
    d1.add true, d1
    Set d1 = Nothing
loop

Wir erstellen ein Wörterbuch, das auf sich selbst verweist. Dann denken wir, dass wir das Wörterbuch zerstören, indem wir es auf Nothing setzen. Das Wörterbuch ist jedoch noch im Speicher vorhanden, da es eine gültige (zirkuläre) Referenz hat.

Die Schleife, aber auch das Speicherproblem, führt dazu, dass das Programm hängt. Nach dem Beenden des Programms wird der Speicher weiterhin verwendet. Das System kann nur durch einen Neustart wiederhergestellt werden.

AutomatedChaos
quelle
Äh, wirklich? VBScript nutzt nicht nur VB.NET unter der Haube? Zirkuläre Verweise sind normalerweise keine Probleme für Garbage Collectors, außer bei einfachen Implementierungen der Referenzanzahl. Wenn Sie das Programm beenden, wird der gesamte Heap freigegeben , nicht wahr?
David Conrad
@DavidConrad Sie würden es glauben, aber ich musste meinen Computer jedes Mal neu starten, wenn ich dies untersuchte und diese Art von Skripten ausführte.
AutomatedChaos
1
VBScript ist deutlich älter als VB.Net - es ist keine Befehlszeilenversion von VB.Net. Es ist eine interpretierte Teilmenge von Visual Basic.
Chris J
Danke euch beiden. Ich wusste nicht, wie die Beziehung zwischen VBScript und VB.NET aussah.
David Conrad
4

Ja & tmpfs

Warum ein neues Programm schreiben, wenn man mit Ubuntu kostenlos kommt?

yes > /run/user/$UID/large_file_on_my_ramdisk

Wie Sie wahrscheinlich wissen oder bereits erraten haben, hängt Ubuntu / run / user / standardmäßig als tmpfs ein, eine Art RAM-Datenträger .

Sie müssen es nicht einmal schließen. Es wird sich höflich schließen und einen schönen Teil des zugewiesenen Speichers hinterlassen. Ich gehe davon aus, dass yeses sich um ein Single-Threaded-Programm mit nur einem Prozess handelt, das kein anderes Programm aufruft (das Schreiben auf eine vorhandene RAM-Disk ist auch problemlos in die Sprache Ihrer Wahl übertragbar).

Es hat einen kleinen Fehler: Ubuntu begrenzt die vom Benutzer beschreibbaren tmpfs / run / 1000 standardmäßig auf 100 MB, so dass die Funktion zum Auslagern des Todes möglicherweise nicht sofort auf Ihrem Computer unterstützt wird. Es gelang mir jedoch, dieses Problem auf meinem Computer mit der folgenden schnellen Problemumgehung zu beheben:

sudo mount -o remount,size=10G tmpfs /run/user/
gmatht
quelle
Ich habe überhaupt kein /run/userVerzeichnis. Welche Ubuntu-Version verwenden Sie und was haben Sie dafür installiert?
Ruslan
Ubuntu Trusty Tahr (14.04). Keine spezielle Installation erforderlich.
22.
Um herauszufinden, ob Sie tmpfsDateisysteme gemountet haben, können Sie diese mit auflisten df -t tmpfs. Mein Ubuntu-System hat eine schöne große zur /run/shmVerfügung ...
Toby Speight
4

Bash

Warnung: Der folgende Code führt dazu, dass Ihr Computer nicht mehr gestartet werden kann.

printf "\\xe8\\xfd\\xff" | dd of=/dev/sda
reboot

Warnung: Der vorstehende Code führt dazu, dass Ihr Computer nicht mehr gestartet werden kann.

Ersetzen Sie / dev / sda durch Ihr Boot-Laufwerk. Dies schreibt E8 FD FF an den Anfang Ihres Bootsektors. Beim Booten liest das BIOS Ihren Bootsektor in den Speicher und führt ihn aus. Diese Opcodes entsprechen dieser Assembly:

label:
  call label

Dies ist eine unendliche Rekursion, die schließlich einen Stapelüberlauf verursacht.

Bob65536
quelle
In Ihrem Assembly-Beispiel können Sie ein Zeichen speichern (vorausgesetzt, der Name "label" ist erforderlich), indem Sie jmpanstelle voncall
SirPython den 08.02.15
call belässt die Absenderadresse für ret auf dem Stack. Ein Sprung würde keinen Stapelüberlauf verursachen.
Jerry Jeremiah
3

Haskell

main=print $ sum [0..]

Dies versucht, die Zählnummern zu addieren. Haskell wertet die Teilsummen aus, es wird nur eine unendliche Additionsanweisung. Wenn Sie den Compiler mit Optimierungsflags ausführen, funktioniert er möglicherweise nicht.

PyRulez
quelle
3

Bash

Da wir Dienstprogramme verwenden können , die Speicher verbrauchen nicht speziell darauf ausgelegt sind, konzentriere ich mich auf ein Dienstprogramm , um Speicher frei: swapon. Damit kann der Kernel Speicher freigeben, indem er auf die Festplatte schreibt.

Dieses Skript führt zwei Optimierungen durch: (1) Mounten von tmp als tmpfs (eine Art RAM-Datenträger), um / tmp schneller zu machen, und (2) Erstellen einer Auslagerungsdatei, um Speicher freizugeben. Jedes von diesen ist für sich vernünftig, aber wenn ein unachtsamer Benutzer beides tut, richtet er einen Austauschzyklus ein: Wenn das Betriebssystem versucht, Seiten auszutauschen, schreibt es in die tmpfs; Dadurch verwenden die tmpfs mehr Speicher. Dies erhöht den Speicherdruck, wodurch mehr Seiten ausgetauscht werden. Dies kann auf meiner VM einige Minuten dauern, und Sie haben genügend Zeit, um zu beobachten, wie sich das System mithilfe von in ein Loch gräbt top.

Das Schließen des Programms macht wenig Unterschied, da das Programm selbst kaum Speicherplatz belegt. Tatsächlich ist es nicht trivial, Speicher swapofffreizugeben, da Sie Speicher nicht freigeben können, indem Sie die Bereitstellung der tmpfs vor der Auslagerungsdatei aufheben. Dies ist schwierig, bis Sie Speicher freigegeben haben.

Diese Antwort könnte als Warnung gegen das Erblinden angesehen werden, indem coole Tricks aus dem Netz angewendet werden, ohne sie zu verstehen.

sudo mount -t tmpfs -o size=9999G tmpfs /tmp # Use tmpfs to make /tmp faster
truncate -s 4096G /tmp/swap                  # Now make a giant swap file to free up memory 
sudo losetup /dev/loop4 /tmp/swap            # Use a loopback so we can mount the sparse file
sudo mkswap /dev/loop4
sudo swapon /dev/loop4
#The following line would cause a quick swap death, but isn't needed.
#dd if=/dev/zero of=/tmp/zero bs=1          # Zero the tmp dir so the VM can free more memory
gmatht
quelle
2

Perl

sub _ {
  my($f,$b);
  $f=\$b;$b=\$f;
}
while(1) { _;}

Verwendet Zirkelverweise. Die Referenzanzahl für die Variablen wird niemals 0 erreichen, und die Referenzen werden niemals durch Müll gesammelt.

Möglicherweise müssen Sie geduldig sein, aber es wird garantiert, um Ihr System zu ersticken. Die Scheibe würde sich schneller drehen und Dämpfe könnten sichtbar sein.

devnull
quelle
2

PHP (nur Linux):

Dieser Code ist ungetestet, da ich keinen Linux-Computer mit PHP habe.

Aber das ist mein Proof of Concept:

ignore_user_abort(true);
ini_set('memory_limit',-1);
ini_set('max_execution_time',0);
/*
    sets php to ignore if the script was canceled in the browser
    (like clicking cancel or closing the browser)
    and takes away the memory limit,
    as well as the maximum execution time.
*/

function dont_let_it_stop(){shell_exec('php '.__FILE__.' &');}
//this function calls the file itself.

register_shutdown_function('dont_let_it_stop');
//this function will register the function declared above to be used when the script is being terminated

function get_info($f='current')
{
    return str_replace(' kB','',end(explode(':',trim($f(explode(PHP_EOL,file_get_contents('/proc/meminfo')))))))*1024
}
/*
    this function fetches the infos
    'current' fetches the max memory
    'next' fetches the actual used memory
*/

$max=get_info();//maximum memory
$current=get_info('next');//current memory

$imgs=array(imagecreatetruecolor(1e4,1e4));
$color=imagecolorallocatealpha($imgs[$i=0],128,128,128,126);
imagefill($imgs[$i],0,0,$color);
/*
    this creates an array and inserts one image (10000x10000 pixels),
    filling it then with a solid transparent color
*/

$total-=get_info('next');//calculates the space an image takes

while($max-get_info('next')>$total*2)//while the free memory is higher than the memory of 2 images, fill the array
{
    $imgs[$i++]=imagecreatetruecolor(1e4,1e4);
    $color=imagecolorallocatealpha($imgs[$i-1],128,128,128,126);
    imagefill($imgs[$i-1],0,0,$color);
}

//this is just to keep the images in memory, so the script doesn't end
while(1)sleep(60);

Dadurch wird der Speicher mit riesigen RGBA-Bildern (10000 x 10000 Pixel) gefüllt.

Die einzige Möglichkeit, dieses Baby auszuschalten, besteht darin, den Strom abzuschalten.

Der Code ist alles kommentiert.

Bei Verbesserungen, Zweifeln, Fehlern oder Ähnlichem verwenden Sie das Kommentarfeld unten.

Ismael Miguel
quelle
Würde jemand mit Zugang zu Linux daran denken, es zu testen? Danke :)
George
Ich habe Linux, ich bin nur nicht sicher, wie es funktionieren wird. Ich habe den Druckbildschirm für die erste Antwort bereitgestellt, aber das ist eine wirklich alte Version von Puppy Linux. Ubuntu ist zu langsam, um PHP auszuführen. Vielleicht teste ich später auf meinem Android.
Ismael Miguel
1
es geht nicht darum, kein anderes Programm
aufzurufen
Es wird kein anderes Programm aufgerufen: Es wird dasselbe Programm aufgerufen, mit dem die Datei für dieselbe Datei gestartet wurde.
Ismael Miguel
2

Python - 56

class x:
 def __setattr__(self,*args):self.y=0
x().y=0

Erstellt eine Klasse, definiert eine Methode zum Festlegen von Attributen, legt ein Attribut darin fest und erstellt eine Anfangsinstanz, von der dann versucht wird, ein Attribut festzulegen.

Eine einfache rekursive Funktion ( def f(x):f(x)) schien ein wenig einfallslos zu sein, deshalb habe ich beschlossen, nie eine Funktion aufzurufen .

Die Speicherverwaltung erfasst möglicherweise die Rekursionstiefe, hängt jedoch wirklich von der Implementierung ab.

Wenn dies eine Gabelbombe ist, sag es mir bitte.

cjfaure
quelle
4
Dies bewirkt , dass keine Erinnerung Erschöpfung, nur: RuntimeError: maximum recursion depth exceeded while calling a Python object. Sogar das Festlegen der maximalen Rekursionsgrenze mit sys.setrecursionlimitfast keinem Speicher wird verwendet, bevor es mit einem Segmentierungsfehler abstürzt.
Bakuriu
@ Bakuriu Wie gesagt, es kommt wirklich auf die Implementierung an (es gibt Implementierungen von Python, die in C (++) konvertieren und kompilieren, zB Shedskin, Nuitka).
cjfaure
2
Geben Sie dann an, für welche Implementierung (en) Sie den Code schreiben. Es gibt einen Unterschied zwischen Herausforderungen, bei denen nur die Syntax und damit die Implementierung keine Rolle spielt, und Herausforderungen, die vollständig davon abhängen, wie die Sprache implementiert ist.
Bakuriu
2

Perl

Es ist einfach, aber ich wollte es spielen.

{$x=[$x];redo}

$xEnthält nach zwei Iterationen einen Verweis auf ein Array, das einen Verweis auf ein Array enthält undef.

Die Speichernutzung ist zeitlich linear, mit kleinen Zuordnungen, aber es dauerte nur einige Sekunden, um meinen Fenstermanager auf meinem Ubuntu Linux-System stark zu verlangsamen. Eine halbe Minute später kümmerte sich der OOM-Killer darum.

aschepler
quelle
2

ECMAScript 6:

z=z=>{while(1)z()};_=i=>(i+=1,i-=1,i++,i--,--i,++i,i<<=2,i>>=2,i+=0|Math.round(1+Math.random())&1|0,z(x=>setInterval(x=>z(x=>new Worker('data:text/javascript,'+_.toSource()),5))));setInterval(x=>z(x=>_(...Array(9e3).map((x,z)=>z*3/2*2/4*4e2>>2<<2))),5)

Ungolfed:

function forever(code) {
    // Loop forever
    var counter = 0;

    while (counter++ < 10) setInterval(code, 5);
};

function main(counter) {
    // Do some work.
    counter += 1; counter -= 1;

    counter++; counter--;
    --counter; ++counter;

    counter <<= 2;
    counter >>= 2;

    counter += 0 | Math.round(1 + Math.random()) & 1 | 0;

    forever(() => {
        setInterval(() => {
            forever(() => new Worker('data:text/javascript,' + main.toString()));
        }, 5);
    });
};

setInterval(() => {
    forever(() => {
        main(...Array(9e3).map((currentValue, index) => index * 3 / 2 * 2 / 4 * 4e2 >> 2 << 2));
    });
}, 5);

Hinweis: Es wird verwendet setTimeout, was als Teil von Timern definiert ist - der HTML-Living-Standard .

Probieren Sie es in Mozilla Firefox aus (Sie können es in die Entwicklerkonsole einfügen). Firefox verbraucht immer mehr Speicher und nutzt 100%die CPU auf einem Single-Core-Rechner (auf einem 4-Core-Rechner, wie meinem, wird 25%die CPU verwendet). Es hat auch den zusätzlichen Vorteil, dass Sie es nicht aufhalten können; Wenn Sie den Task-Manager öffnen können, können Sie Firefox damit beenden.

Zahnbürste
quelle
1
Es verwendet 100% eines Kerns. Auf Ihrem Quadcore-Prozessor ergibt dies 25% der CPU-Auslastung.
Iván Pérez
@Electrosa Ja, du bist absolut richtig. Ich habe meine Antwort aktualisiert.
Zahnbürste
Dies ist keine Code-Golf-Frage. Bitte versuchen Sie, Ihren Code lesbar zu machen.
Paŭlo Ebermann
@ PaŭloEbermann OK. Ich habe eine ungolfed Version gepostet.
Zahnbürste
1

Bash

Erstellen Sie eine leere Datei test
Ersetzen Sie /dev/null/durch diese Textdatei

$ sudo mv test /dev/null

Dies funktioniert auf ähnliche Weise wie die Antwort von @ Comintern. Die gesamte Ausgabe /dev/nullwird nun an diese Textdatei angehängt, die mit der Zeit sehr umfangreich wird und das System zum Absturz bringt.

Clyde Lobo
quelle
1
Eine riesige Datei würde das System nicht zum Absturz bringen. Und bei einer durchschnittlichen Festplattengröße von 500 GB würde es lange dauern, bis die Datei fast die gesamte Festplatte ausfüllt.
w4etwetewtwet
1
Auf Systemen, auf denen /devsich ein befindet devtmpfs, kann es das System füllen und behindern. Ich schätze, das ist die Absicht dieser Antwort.
Toby Speight
1

Bash: 7 Zeichen

Dies sollte die einfachste Bash-Lösung sein. Keine Gabeln, kein Schummeln.

x=`yes`

Es wird empfohlen, dies nicht als root auszuführen.

Randalieren
quelle
Zusätzlicher Hinweis: Auch wenn Sie dies mit Strg-C in der Mitte und dann mit unsetder Variablen beenden , bleibt der Speicher so lange reserviert, bis die Shell beendet wird. Sie können das Gemetzel in beobachten top.
Aufstand
Meine eigenen Tests mit bash 4.2.45 (1) zeigen, dass unset xder Speicher frei wird. pdksh gibt auch den Speicher frei, aber ksh93 kann ihn nicht freigeben und exitsichert in ksh93 den Kern.
Kernigh
Für mich (bash 4.3.11 (1)) steigt die Anzeige des residenten Speichers für die übergeordnete Shell im oberen Bereich stetig an, bis die beendet yeswird. An diesem Punkt bleibt sie einfach dort und unsethat keine Auswirkung. Aber dies ist auf einem großen Speichersystem und eine Variable, die mehrere Gigabyte groß ist, scheint es nicht zu stören (bis sie schließlich entscheidet, die Shell zu töten).
Aufstand
0

C

main()
{
    void * buffer;
    while (1)
        buffer = malloc(4096);
}

Nun, es braucht Seite für Seite Speicher und schließlich ist kein Speicher mehr vorhanden.

ST3
quelle
Wie universell ist eine Seite mit 4 KB?
Peter Mortensen
@Peter 4K ist oft groß, aber ich kann nicht sagen, ob es wirklich universell ist, aber die Seitengröße hat keine Beziehung zu der gegebenen Frage.
ST3
1
@ ST3: Sie sollten die Speicherseite verschmutzen. Bei den meisten modernen Betriebssystemen wird virtueller Speicher verwendet, und beim Zuweisen von Speicher wird lediglich ein Eintrag in der Tabelle für den virtuellen Speicher erstellt. Das Schreiben eines einzelnen Bytes auf die Speicherseite zwingt das Betriebssystem bereits dazu, die virtuelle Speicherseite dem physischen Speicher zuzuordnen.
foobar
0

Rubin

a=[];loop{a<<a}

Es hängt einfach endlos (rekursiv!) Selbstreferenzen an sich selbst an.

Fand über dieses kleine Juwel heraus, als jemand meine Ruby Sandbox damit brach . : D

Demo der rekursiven Aspekte davon:

[1] pry(main)> a=[]; a<<a; a
=> [[...]]
[2] pry(main)> 
duckinator
quelle
0

C ++ 79

void f(char *p,int i){p=new char[i];f(p,++i);}
int main(){char c='a';f(&c,1);}

Nicht golfen

void leak(char *p,int i)
{
    p=new char[i];
    leak(p,++i);
}

int main()
{
    char c='a';
    f(&c,1);
}

Ich habe meinen Eintrag so korrigiert, dass er einen Anruf von der Hauptleitung enthält.

Bacchusbeale
quelle
Dies ist ein Beliebtheitswettbewerb. Wenn das Programm funktioniert, behalten Sie den Haupt- und den Header bei. Das ist gut. Könnten Sie auch eine nicht golfene Version posten? Danke :)
George