Crear una pérdida de memoria, sin bombas de horquilla [cerrado]


54

Su tarea es crear una pérdida de memoria . Este es un programa que utiliza mucha memoria, hasta que la computadora se agota y tiene que hacer algunos cambios para evitar que se agote. La única forma de liberar la memoria es matando el programa en el administrador de tareas o usando una línea de comando kill como taskkill /im yourprogram /f(en Windows) o incluso reiniciando la computadora. El simple hecho de cerrar la aplicación no debería evitar que continúe acaparando la memoria.

Reglas:

  1. Las bombas de horquilla de cualquier tipo están prohibidas. ¡Eso significa que la infame línea Bash:(){ :|:&};: está prohibida!

  2. La aplicación debe ser de un solo subproceso. Esto implica la regla de la bomba tenedor.

  3. El programa no debe ejecutar otros programas. Esto significa que no puedes hacer algo así run(memoryfiller.exe). La única excepción a esto son los programas que se incluyen con su sistema operativo o idioma, que no están diseñados principalmente para consumir memoria (es decir, tienen otro propósito). Esto significa que cosas como caty ln -sestán permitidas.

  4. Puede tomar tanta memoria como desee. Mientras más, mejor.

  5. El código debe explicarse completamente.

Buena suerte. Este es un concurso de popularidad, por lo que gana el código con más votos después de 10 días desde la fecha de solicitud.


8
"Cerrarlo todavía debería hacerlo memoria de memoria": si un programa es un ejecutable de shell (como lo son la mayoría de las versiones de Windows de los intérpretes de lenguaje de scripting), cerrar su ventana matará al programa.
mniip

54
¿No es esto justo while(1)malloc(999);?
Pomo de la puerta

10
No estoy seguro de si "Cerrarlo aún debería hacerlo memoria de cerdo" es compatible con "La aplicación debe ser de un solo subproceso". Si ningún hilo tiene una gran cantidad de memoria, el sistema operativo puede recuperarlo, ¿verdad?
aebabis

51
Simplemente ejecute firefox 26 con algunas pestañas abiertas y ejecutando flash durante media hora. Pondrá a su computadora de rodillas.
Braden Best

1
@mniip. Ese es el objetivo del desafío. Hacer un desafío difícil. Y pomo de la puerta. ¡Quería algo diferente! ;)
George

Respuestas:


78

Ventanas

La API Win32 le permite asignar memoria en otros procesos y luego leer / escribir esa memoria de forma remota. Este programa tiene solo un subproceso, que utiliza para enumerar cada proceso en ejecución en el sistema, y ​​luego asigna repetidamente buffers de 1 MB en cada proceso hasta que la asignación falla. Cuando termina con un proceso, pasa al siguiente. Las asignaciones no se liberan cuando finaliza el programa de llamada, solo cuando / si finaliza cada proceso de destino. Esto cuelga una máquina virtual Windows 7 de 2GB en aproximadamente 10 segundos. Requiere correr como administrador.

Compilar: 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;
}

99
Windows es malvado.
tomsmeding

44
Necesito cerrar esta noche. Voy a intentar esto;)
George

1
"(se ejecuta como un usuario normal, no utiliza privilegios de administrador" - no estoy seguro de esto, necesita SeDebugPrivilege, que por defecto no está presente en el token del usuario normal
rkosegi

@rkosegi Gracias, arreglado.
Andrew Medico

14
+1 Esto merece muchos votos positivos, ya que hasta ahora es la única respuesta que cumple con el Cierre original , aún así debería hacer que sea un requisito de memoria de cerdo . Solución muy creativa :-)
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();
    } 
  }
}

Explicación

Puede suponer que, dado que no hay referencias en el código (aparte de countlo que puede ignorar con seguridad), no puede filtrarse. Sin embargo, el finalizador crea dos nuevas Hydras, y aunque tampoco contiene referencias para estos, se quedarán hasta que finalicen. Esto significa que el programa solo pierde memoria durante la recolección de basura, de ahí las llamadas a System.gc()y System.runFinalization().


77
@TimS. ¿¡¿dónde está tu Dios ahora?!?
Cruncher

¿Son System.gc()y System.runFinalization()necesarios? Es decir, ¿gc se ejecutará aleatoriamente a veces, o tiene que llenar algo de memoria o llamar a gc?
Cruncher

44
En un programa típico, System.gc()y System.runFinalization()no sería necesario. La recolección de basura ocurriría naturalmente debido a la presión de la memoria. Sin embargo, en esta aplicación no hay presión de memoria hasta que la recolección de basura comienza a ejecutarse. Pensé en introducir artificialmente algunos (por ejemplo, moviéndome new Hydra()dentro del bucle), pero pensé que esto era más malvado.
James_pic

1
Sí, no presté mucha atención a la advertencia de "Cerrarlo todavía debería hacerlo memoria de cerdo", ya que no parecía significativo (aparte de los hacks de sistema operativo como @ german_guy's). Java siempre hace girar un hilo de finalización, por lo que tal vez no haya forma de que una aplicación Java obedezca la regla # 2.
James_pic

1
En los sistemas Unix, no puede bloquear SIGKILL (señal 9), por lo que no puede hacer que su programa sea imparable (bueno, excepto si logra llevarlo a un estado de espera ininterrumpida ... así que quizás elimine a distancia un servidor NFS cuyos archivos usted el acceso podría funcionar ;-))
celtschk

37

C

Usando el lenguaje de programación C y probado con el kernel de Linux 2.6.32-49-generic y libc-2.11.1.so.

La única forma de liberar la memoria es matando el programa en el administrador de tareas o usando taskkill / im yourprogram / f o incluso reiniciando la PC.

Esto se logra bloqueando cualquier señal, excepto SIGKILL y SIGSTOP.

Cerrarlo aún debería hacer que acapare la memoria.

Esto realmente me confundió ... Matarlo o cerrarlo resulta en la finalización del proceso, lo que permite que el sistema operativo recupere cualquier memoria asignada por el proceso. Pero luego pensé que cerrándolo podría significar cerrar la terminal o cualquier otro proceso principal que ejecute el proceso de pérdida de memoria. Si acerté, resolví este problema bloqueando cualquier señal, lo que convierte el proceso en un demonio cuando el proceso padre finaliza. De esa manera, puede cerrar el terminal en el que se está ejecutando el proceso y continuará ejecutándose y se procederá a la pérdida de memoria.

Las bombas de horquilla de cualquier tipo están prohibidas. ¡Eso significa que bash infame: () {: |: &} ;: está prohibido!

El proceso no se bifurca.

La aplicación debe ser de un solo subproceso. Esto implica la regla de la bomba tenedor

No se generan nuevos hilos.

El programa no debe ejecutar otro programa. Esto significa que no puede hacer algo como ejecutar (memoryfiller.exe)

No se generan nuevos procesos.

Puede tomar tanta memoria como desee. Mientras más, mejor.

Tanto como el sistema operativo puede proporcionar.

El código debe explicarse completamente.

Comentarios agregados a la fuente.

Y finalmente aquí está el código:

#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;
}

Para cualquiera que esté interesado en lo que sucede si mantiene este programa en funcionamiento: en mi sistema de prueba con 2 GB de RAM y 4 GB de espacio de intercambio, tardé unos 10 minutos en llenar la RAM e intercambiar. El asesino de OOM comenzó su trabajo y tres minutos después todos los procesos han sido eliminados. Incluso el mouse, el teclado y la pantalla han sido eliminados por el sistema. /var/log/kern.log no muestra información útil, excepto los procesos que se han eliminado.


Edité la fuente para hacer que el asesino de Oom ignore el proceso y elimine procesos inocentes para liberar memoria.
foobar

55
Para cualquiera que esté interesado en lo que sucede si mantiene este programa en funcionamiento: en mi sistema de prueba con 2 GB de RAM y 4 GB de espacio de intercambio, tardé unos 10 minutos en llenar la RAM e intercambiar. El asesino de OOM comenzó su trabajo y tres minutos después todos los procesos han sido eliminados. Incluso el mouse, el teclado y la pantalla han sido eliminados por el sistema. /var/log/kern.log no muestra información útil, excepto los procesos que se han eliminado.
foobar

Jaja, eso es maravilloso! Debería editar esa descripción en su respuesta. +1
Pomo de la puerta

1
No voté en contra, pero sería bueno si el código pudiera formatearse para que no sea necesario desplazarse horizontalmente para leer los comentarios.
Paŭlo Ebermann

2
+1 para 1) hacer que los procesos que entregan dispositivos de entrada / salida se eliminen y 2) crear un programa difícil de rastrear desde los registros. Estos son los niveles de maldad que rizan el bigote.
Kevin - Restablece Monica

29

Pure Bash

No es una bomba tenedor, lo prometo:

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

Se parece mucho a una bomba tenedor, y utiliza una técnica recursiva similar, pero no tenedores. Por supuesto, esto ejecutará su shell sin memoria, por lo que se recomienda iniciar un nuevo shell antes de pegar este comando.

  • Definir una función llamada :
  • La función simplemente se llama recursivamente con $@(lista arg) duplicada
  • Después de la definición de la función, la :función se llama con un argumento inicial:

Salida:

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

En una edición anterior de esta respuesta lo hice a=$(yes), pero noté la regla "El programa no debe ejecutar otro programa", por lo que necesito usar puro en su bashlugar sin llamar a ningún coreutils ni a ninguna otra cosa.


Aqui hay otro más:

POR FAVOR NO HAGA FUNCIONAR ESTO EN UNA MÁQUINA DE PRODUCCIÓN

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

Una vez más, esto no es una bomba tenedor: todo se ejecuta desde un hilo. Este parece bastante útil para poner de rodillas a mi Ubuntu VM, con poco espacio para la recuperación, aparte de reiniciar.

Como en la clásica bomba tenedor, :()se define una función recursiva . Sin embargo, no desvía las llamadas a sí mismo. En cambio, se llama a sí mismo con un argumento, que se llama a sí mismo en una sustitución de proceso . Debido a que la sustitución de procesos funciona al abrir un descriptor de archivo /dev/fd/n, esto no solo consume memoria del proceso (bash), sino que también consumirá algo de memoria del núcleo. En mi máquina Ubuntu, esto tiene el efecto de hacer que el administrador de ventanas deje de funcionar después de unos segundos, luego, poco después de terminar con esta pantalla:

enter image description here

Al hacer clic OK, aparece esta pantalla:

enter image description here

Ninguna de estas opciones parece ser de gran ayuda; en este punto, reiniciar parece ser la única buena opción.


3
$ which yes->/usr/bin/yes
Izkata

2
"La única forma en que se puede liberar la memoria es matando el programa en el administrador de tareas o usando taskkill / im yourprogram / f o incluso reiniciando la PC. Cerrarlo aún debería hacer que acapare la memoria". >> El bash se puede terminar usando un SIGTERM, por lo que no es necesario matarlo para que deje de ejecutarse. También deja de ejecutarse cuando el sistema se queda sin memoria. Una vez que el bash terminó, ya sea por SIGTERM o por quedarse sin memoria, la memoria se devuelve al sistema operativo.
foobar

Esto no funciona para mí ... más o menos ... puedo ver que la memoria desaparece gradualmente, pero esto sucede muy lentamente y también se puede eliminar simplemente presionando ctrl + c. Está funcionando ahora durante 1 minuto y está ocupado aproximadamente 1 GB. Tengo una máquina MUY rápida ... pero eso no debería importar, ¿verdad?
Stefanos Kalantzis

Respondiendo a mi propio comentario: El comando en realidad mató al bash después de aproximadamente 2 minutos y 49 segundos. Originalmente supuse que iba a ser instantáneo en base a esta respuesta.
Stefanos Kalantzis

@StefanosKalantzis Gracias por sus comentarios. Me hizo pensar un poco más y acabo de encontrar un fragmento de shell aún más malvado - ver edición.
Trauma digital

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;"/>

Luego, pase el documento a un analizador XML que no haga detección de bucle / recursión de referencia de entidad. Por ejemplo, xpathincluido con perl:

xpath boom.xml /

Cómo funciona:

  1. El analizador encuentra <boom a="&a;">
  2. El analizador se expande "&a;"en"&b;&b;"
  3. El analizador se expande uno de los "&b;"en "&c;&c;"(en el retorno, se expandirá el otro "&b;")
  4. El analizador expande uno de los "&c;"etc.

Si pudiera ocurrir una expansión completa, habría una expansión de 2 ^ 52 de "ka-boom!". Suponiendo 2 bytes por carácter, intentará usar 64 PiB. La expansión va "ka-boom!" a la vez, por lo que generalmente puede verlo usar toda la memoria en la parte superior.

Esto tiene varios nombres, buena descripción aquí: http://projects.webappsec.org/w/page/13247002/XML%20Entity%20Expansion


3
Esencialmente, una copia de Billion se ríe
Cole Johnson

@ColeJohnson Sí, eso es todo! Contribuí al proyecto de clasificación de amenazas de WASC, así que me sentí obligado a señalar WASC en lugar de Wikipedia. :)
ɲeuroburɳ

22

C ++

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

¡Este código fue inesperado! Colgó mi computadora mientras el administrador de tareas estaba abierto y mostró que tomó 890 Mb de memoria en 1 segundo y luego también se colgó. No sé cómo funciona esto, tal vez sigue dando memoria a una variable. Para explorar más de este código, agregué una declaración delete a;y todo estuvo bien durante la prueba (sin bloqueo) Entonces, creo que la porción de memoria es dado (debido a new int) y luego devuelto (debido a delete a) al espacio libre en el nuevo código a continuación.

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

Por lo tanto, concluyo que ¡ NO RAM EN ESTE MUNDO PUEDE MANEJAR ESTE CÓDIGO!

EDITAR : Pero muchos procesadores pueden, por ejemplo intel core 2 duo, no pueden manejar este código pero
intel core i-series pueden (funcionó para mí ...)

Recuerde que la respuesta a la pregunta es el primer código, el segundo es para explicación.


99
Agradable, el compilador cree que todavía va a usar el new intdispositivo aunque sobrescribió el puntero, por lo que nunca podrá acceder a él nuevamente ... Así que no se llama a la recolección de basura y llena la memoria más rápido que un niño gordo come bolos
David Wilkins

37
@DavidWilkins: ... esto es C ++, C ++ no tiene recolector de basura.
Phoshi

32
Si es inesperado para usted que este código se filtre, entonces creo que no debería usar C ++ hasta que lo aprenda mejor.
svick

1
@svick ¡Pero no es como golpear el tablero de dardos en la oscuridad! Tenía una idea de que esto hará el trabajo que la pregunta quiere.
Mukul Kumar

15
@svick ¿Cómo demonios se supone que debe "aprenderlo mejor" si "no debería usar C ++"?
Kevin

16

BrainFuck

+[>+]

Explicación:

Para ingresar al bucle, aumenta la celda a 1. Se mueve a la siguiente celda aumentando eso a 1 siempre que la última celda sea positiva.

Por lo general, un intérprete BrainFuck tiene fallas al tener un límite estricto para el número de celdas en la cinta, pero algunos intérpretes agregan celdas dinámicamente. Estos continuarán consumiendo memoria hasta que ya no se consuma.

beefes uno de esos intérpretes y está disponible en el Centro de software de Ubuntu y mi ejecución actual en una máquina no utilizada comenzó hace 29 horas y ha consumido 1 GB de RAM en ese momento. Aquí está la salida detop

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

Tiene 4 GB de caché y 6 GB de intercambio, así que supongo que actualizaré esta respuesta con cómo fue en unos 12 días.

ACTUALIZACIÓN 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    

ACTUALIZACIÓN 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   

Así que ha estado funcionando durante 10 días. Parece que se ejecutará durante al menos 10 más antes de que ocurra algo interesante.


Agradable y corto.
nrubin29

15

C y POSIX

Aquí estoy apuntando a una solución altamente portátil. El problema es que C puro no parece tener una manera de decirle al sistema operativo que la memoria debe permanecer asignada después de que se cierra el programa. Entonces me permito usar POSIX; la mayoría de los sistemas operativos tienen cierta demanda de compatibilidad POSIX, incluidos Windows, Linux y MacOS X. Sin embargo, solo lo he probado en Ubuntu 12.04 de 32 bits. No requiere permisos de superusuario.

Esta solución es esencialmente la while(1){malloc(1);}solución tradicional . Sin embargo, en lugar de malloc, utiliza las funciones de memoria compartida POSIX. Dado que asigna un identificador de memoria compartida a cada asignación, aún es posible acceder a la memoria una vez que finaliza el proceso. Por lo tanto, el núcleo no puede liberar la memoria.

#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*/
  }
}

El mejor y más brillante C responde IMO. +1
syb0rg

1
Buena esa. La primera solución que se me ocurrió fue la de Andrew Medico, pero como eso no es posible en Linux y como no me gusta la programación de Windows, quería filtrar la memoria compartida, pero no podía recordar los nombres de las funciones POSIX. Gracias por recordarme de ellos;) Todo lo que encontré fue solo cosas de mmap que no están asignadas en la terminación del proceso ...
foobar

14

C#

Olvidar darse de baja de los eventos antes de que el controlador salga del alcance hará que .NET pierda memoria hasta que arroje OutOfMemoryException.

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;
    }
}

Explicación : Dentro del whilebucle, construimos un nuevo objeto, lo que hace que el marco asigne más memoria, pero también evitamos que Bse libere la nueva instancia cuando sale del alcance al asignar un método de instancia a un evento en una clase diferente, el resultado es que la nueva instancia de se Bvuelve inalcanzable desde nuestro código, pero todavía existe una referencia, lo que significa que el GC no la lanzará hasta que atambién esté fuera de alcance.

Los eventos estáticos tienen el mismo escollo, ya que nunca salen del alcance, solo se limpian cuando finaliza el proceso, a menos que primero se dé de baja del evento. ¡Siempre almacene sus referencias, gente!

using System;

class Program
{
    static event Action Event;

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

Lo anterior funciona con la misma idea, el controlador se vuelve inalcanzable una vez que el whilebucle se sale del alcance, lo que hace imposible darse de baja del evento, lo que significa que la memoria se quedará allí hasta que el programa finalice. Los eventos estáticos son posiblemente más peligrosos que los eventos de instancia, porque puede asegurarse de que nunca se salgan del alcance.

EDITAR : También puede hacer lo mismo básicamente con cualquier otro objeto, siempre que agregue una referencia y al mismo tiempo se asegure de que no haya forma de liberar esa referencia.

Aquí hay un ejemplo que usa objetos estáticos y matrices.

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 );
    }
}

Las matrices se siguen agregando a la lista, pero no hay forma de borrar la lista sin modificar el código, lo que sería imposible para las aplicaciones de código cerrado. Aumentar el número pasado Leak.Addhará que se filtre más rápido, si lo configura lo suficientemente alto, solo se generará una excepción OverflowException inmediata.


10

bash (sin utilidades externas)

No hay bomba tenedor aquí.

Advertencia: podría matar tu caparazón.

Solo trato de crear una matriz de enteros para referencia porque sigo olvidando cómo se ven los enteros.

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

Resultados en:

xmalloc: expr.c:264: cannot allocate 88 bytes (268384240 bytes allocated)

2
+1 para "porque sigo olvidando cómo se ven los enteros" :)
David Conrad

8

J (7)

ADVERTENCIA: Esto congeló mi sistema cuando lo probé (Windows 8, J 8.01, en el terminal qt).

2#^:_[_
  • 2# duplica la longitud del argumento duplicando cada elemento,
  • ^:_ encuentra el punto fijo de la función dada (pero no hay una, por lo que se repite sin parar)
  • [_lo llama _como argumento.

8

Haskell (número de Graham)

Es muy simple: calcula el número de Graham

A diferencia de otros ejemplos aquí, no se ejecutará para siempre ... usará mucha CPU, pero en teoría podría terminar. si no fuera por el hecho de que almacenar el número ...

el universo observable es demasiado pequeño para contener una representación digital ordinaria del número de Graham, suponiendo que cada dígito ocupe un volumen de Planck .

(según 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

Entonces, la idea es que la memoria será utilizada por una (serie de cada vez más) enorme Integer(s) (los enteros de Haskell son de tamaño arbitrario).

Si desea probarlo, es posible que deba aumentar el tamaño de la pila o cargarlo dentro ghci.


2
Un universo tonto, que no se ajusta al estándar Haskell para enteros. ¿Por qué no puede soportar un tamaño arbitrario?
PyRulez

6

Inspirado por @comintern.

Reemplazo / dev / null. Involucrando el modo furtivo. Requiere encabezados de kernel, modo de superusuario y un compilador que funcione.

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

Que te diviertas.

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

Código fuente:

#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 <florian@n0la.org>");
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);

¡Advertencia, esto puede obligarlo a reiniciar!

Para eliminarlo:

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

6

Rubí

Todos saben que suma (1 / n ^ 2) = pi ^ 2/6

Entonces puedo definir una función de aproximación:

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

p pi_approx.(100_000)

Por supuesto, el (1..infinito) se volverá loco.

Sin embargo, tenga en cuenta que el uso de lazy hará que esto funcione;)

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

5

C - 28 25 caracteres (programa completo)

¡No ejecute ese, o su sistema se congelará rápidamente!

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

La llamada a malloc reservará 9 bytes de memoria y solicitará regularmente nuevas páginas de memoria al sistema operativo. La memoria asignada por malloc se filtra inmediatamente ya que no se almacena ningún puntero a la dirección devuelta. Una vez que el sistema se ha quedado sin memoria (RAM y espacio de intercambio) o se alcanza el límite de memoria para el proceso, el programa saldrá del ciclo while y terminará.


2
No por mucho tiempo: cualquier sistema razonablemente moderno debe tener un asesino OOM que intervenga y elimine el proceso. Al menos Ubuntu 12.04 lo hace.
Trauma digital

1
Bueno, me bloqueé mi Ubuntu 13.10 al probar este código ...
Mathieu Rodic

@DigitalTrauma ¿Por ejemplo, FreeBSD tiene un OOMK?
Ruslan

1
main(){while(malloc(9));}guarda otros 3 caracteres y llena mi memoria casi instantáneamente.
gmatht

@gmatht: gracias por la sugerencia! Edité la respuesta ... aunque me gustó la idea de aumentar el tamaño del bloque en cada bucle.
Mathieu Rodic

4

VBScript

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

Estamos creando un dicionario que apunta a sí mismo. Luego pensamos que destruimos el diccionario al establecerlo en Nothing. Sin embargo, el diccionario todavía existe en la memoria porque tiene una referencia válida (circular).

El bucle, pero también el problema de la memoria, hace que el programa se bloquee. Después de apagar el programa, la memoria todavía está en uso. El sistema solo se puede restaurar reiniciando.


Uh, enserio? ¿VBScript no solo usa VB.NET bajo el capó? Las referencias circulares normalmente no son problemas para los recolectores de basura, excepto para implementaciones de recuento de referencias simples, y la finalización del programa debería dar como resultado la liberación de su montón completo , ¿no?
David Conrad

@DavidConrad Lo pensarías, pero tuve que reiniciar mi máquina cada vez que investigué esto y ejecuté este tipo de scripts.
AutomatedChaos

1
VBScript es anterior a VB.Net significativamente: no es una versión de línea de comandos de VB.Net; Es un subconjunto interpretado de Visual Basic heredado.
Chris J

Gracias a los dos. No me di cuenta de cuál era la relación entre VBScript y VB.NET.
David Conrad

4

Sí y tmpfs

¿Por qué escribir un nuevo programa cuando uno viene gratis con Ubuntu?

yes > /run/user/$UID/large_file_on_my_ramdisk

Como probablemente sepa, o ya lo ha adivinado, Ubuntu se monta / ejecuta / usuario / por defecto como tmpfs, que es un tipo de disco RAM .

Ni siquiera tiene que cerrarlo. Se cerrará cortésmente, dejando una buena porción de memoria asignada. Supongoyes es un programa de un solo proceso y un solo subproceso que no llama a ningún otro (escribir en un disco RAM existente también es trivialmente portátil para el idioma de su elección).

Tiene un error menor: Ubuntu limita la escritura del usuario tmpfs / run / 1000 a 100 MB de forma predeterminada, por lo que es posible que la función de cambio de muerte no sea compatible con su máquina de fábrica. Sin embargo, logré arreglar esto en mi máquina con la siguiente solución rápida:

sudo mount -o remount,size=10G tmpfs /run/user/

No tengo un /run/userdirectorio en absoluto. ¿Qué versión de Ubuntu usa y qué instaló para esto?
Ruslan

Ubuntu Trusty Tahr (14.04). No se necesita instalación especial.
gmatht

Para saber si tiene algún tmpfssistema de archivos montado, puede enumerarlos con df -t tmpfs. Mi sistema Ubuntu tiene un gran grande /run/shmdisponible ...
Toby Speight

4

Golpetazo

Advertencia: el siguiente código hará que su computadora no se pueda iniciar.

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

Advertencia: el código anterior hará que su computadora no se pueda iniciar.

Reemplace / dev / sda con su unidad de arranque. Esto escribe E8 FD FF al comienzo de su sector de arranque. Al arrancar, el BIOS lee su sector de arranque en la memoria y lo ejecuta. Esos códigos de operación son equivalentes a esta asamblea:

label:
  call label

Esta es una recursión infinita, que eventualmente causará un desbordamiento de la pila.


En su ejemplo de ensamblaje, puede guardar un carácter (suponiendo que el nombre "etiqueta" es necesario) usando en jmplugar decall
SirPython

La llamada deja la dirección de retorno en la pila para ret. saltar no causaría un desbordamiento de la pila.
Jerry Jeremiah

3

Haskell

main=print $ sum [0..]

Esto intenta sumar los números de conteo. Haskell evalúa las sumas parciales, simplemente se convierte en una declaración de suma infinita. Si ejecuta el compilador con indicadores de optimización, es posible que no funcione.


3

Golpetazo

Ya que podemos utilizar los servicios públicos que no están diseñados específicamente para consumir memoria, me centro en una utilidad para liberar memoria: swapon. Esto se utiliza para permitir que el núcleo libere memoria escribiendo en el disco.

Este script realiza dos optimizaciones: (1) Montaje de tmp como tmpfs (un tipo de disco RAM) para hacer / tmp más rápido y (2) crear un archivo de intercambio para liberar memoria. Cada uno de estos son razonables por sí mismos, pero si un usuario descuidado hace ambas cosas, establece un ciclo de intercambio: cuando el sistema operativo intenta intercambiar páginas, escribe en el tmpfs; esto hace que los tmpfs usen más memoria; Esto aumenta la presión de la memoria y hace que se intercambien más páginas. Esto puede tardar unos minutos en mi VM, mucho tiempo para que vea cómo el sistema se excava en un agujero utilizando top.

Cerrar el programa hace poca diferencia ya que el programa en sí mismo apenas asigna memoria. De hecho, no es trivial liberar memoria ya que no puede liberar memoria desmontando el tmpfs antes que swapoffel archivo de intercambio, y eso es difícil de hacer hasta que haya liberado la memoria.

Esta respuesta podría considerarse una historia de advertencia contra el cegamiento aplicando trucos geniales desde la red sin entenderlos.

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

2

Perl

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

Utiliza referencias circulares. El recuento de referencias para las variables nunca alcanzará 0, y las referencias nunca se recolectarán como basura.

Es posible que deba ser paciente, pero se garantiza que estrangulará su sistema. El disco comenzaría a girar más rápido y los humos podrían ser visibles.


2

PHP (solo Linux):

Este código no se ha probado, ya que no tengo una computadora Linux con php ejecutándose.

Pero esta es mi prueba de concepto:

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);

Esto llenará la memoria con enormes imágenes RGBA (10000x10000 píxeles).

La única forma de apagar a este bebé es apagando la energía.

El código está todo comentado.

Cualquier mejora, duda, error o cualquier cosa, use el cuadro de comentarios a continuación.


¿Alguien con acceso a Linux le importaría probarlo? Gracias :)
George

Tengo Linux, pero no estoy seguro de cómo funcionará. Proporcioné la pantalla de impresión para la primera respuesta, pero esa es una versión muy antigua de linux cachorro. Ubuntu es demasiado lento para ejecutar php. Tal vez lo pruebo en mi Android más tarde.
Ismael Miguel

1
falla el punto de no llamar a otro programa
Einacio

No está llamando a otro programa: está llamando al mismo programa que inició el archivo para el mismo archivo.
Ismael Miguel

2

Python - 56

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

Crea una clase, define un método para establecer atributos, establece un atributo en ella y crea una instancia inicial de la que luego intenta establecer un atributo.

Una simple función recursiva ( def f(x):f(x)) parecía poco imaginativa, así que decidí no llamar nunca una función.

La administración de memoria puede capturar la profundidad de recursión, pero realmente depende de la implementación.

Si esto es una bomba tenedor, por favor dígame.


44
Esto no causa agotamiento de la memoria, a: RuntimeError: maximum recursion depth exceeded while calling a Python object. Incluso establecer el límite máximo de recursión sys.setrecursionlimitcasi sin memoria se usa antes de que falle con una falla de segmentación.
Bakuriu

@Bakuriu Como dije, realmente depende de la implementación (hay implementaciones de Python que se convierten a C (++) y se compilan, por ejemplo, Shedskin, Nuitka).
cjfaure

2
Luego indique para qué implementación (es) particular (es) está escribiendo el código. Hay una diferencia entre los desafíos donde solo importa la sintaxis y, por lo tanto, la implementación no es relevante, y los desafíos que dependen completamente de cómo se implementa el lenguaje.
Bakuriu

2

Perl

Es simple, pero tenía ganas de jugar al golf.

{$x=[$x];redo}

Después de dos iteraciones, $xcontiene una referencia a la matriz que contiene una referencia a la matriz que contiene undef.

El uso de la memoria es lineal en el tiempo, con pequeñas asignaciones, pero solo tardó varios segundos en ralentizar severamente mi administrador de ventanas en mi sistema Ubuntu Linux. Medio minuto después, el asesino de OOM se encargó de ello.


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)

Sin golf:

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);

Nota: Utiliza setTimeout, que se define como parte de Timers: el estándar de vida HTML .

Pruébelo en Mozilla Firefox (puede pegarlo en la consola del desarrollador). Firefox sigue consumiendo más y más memoria, y usa 100%la CPU en una máquina de un solo núcleo (en una máquina de 4 núcleos, como la mía, usa 25%la CPU). También tiene el beneficio adicional de que no puede detenerlo; si puedes abrir el administrador de tareas, puedes matar a Firefox con él.


1
Utiliza el 100% de un núcleo. En su procesador quadcore, eso resulta en un 25% del uso de la CPU.
Iván Pérez

@Electrosa Sí, tienes toda la razón. He actualizado mi respuesta.
Cepillo de dientes

Esta no es una pregunta de código de golf, intente que su código sea legible.
Paŭlo Ebermann

@ PaŭloEbermann OK. He publicado una versión sin golf.
Cepillo de dientes

1

Golpetazo

Crear un archivo vacío test
Reemplazar /dev/null/con este archivo de texto

$ sudo mv test /dev/null

Esto funciona de manera similar a la respuesta de @Comintern. Toda la salida /dev/nullahora se agregará a este archivo de texto, que con el tiempo se volverá enorme y bloqueará el sistema.


1
Un archivo enorme no bloqueará el sistema. Y suponiendo un tamaño de disco promedio de 500 gb, el archivo tardaría mucho tiempo en llegar a llenar el disco.
w4etwetewtwet

1
En los sistemas donde /deves a devtmpfs, puede llenarse y obstaculizar el sistema. Supongo que esa es la intención de esta respuesta.
Toby Speight

1

Bash: 7 caracteres

Esta debería ser la solución bash más simple. Sin tenedores, sin trampas.

x=`yes`

Se recomienda no ejecutar esto como root.


Nota adicional: incluso si termina esto con ctrl-c a mitad de camino, y luego unsetla variable, la memoria permanece asignada hasta que se destruye el shell. Puedes ver la carnicería en top.
Riot

Mis propias pruebas con bash 4.2.45 (1) muestran que unset xlibera la memoria. pdksh también libera la memoria, pero ksh93 no puede liberarla, y exiten ksh93 vuelca el núcleo.
kernigh

Para mí (bash 4.3.11 (1)), la pantalla de memoria residente en la parte superior para el caparazón principal sube de manera constante hasta que yesse elimina, en cuyo punto simplemente permanece allí, unsetsin ningún efecto. Pero esto está en un sistema de memoria grande y tener una variable de varios gigabytes no parece molestarlo (hasta que finalmente decide matar el shell).
Disturbios

0

C

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

Bueno, se necesita memoria página tras página y finalmente no queda memoria.


¿Cuán universal es una página de 4 KB?
Peter Mortensen

@Peter 4K a menudo es de tamaño, pero no puedo decir si es realmente universal, pero el tamaño de página no tiene relación con la pregunta dada.
ST3

1
@ ST3: debe ensuciar la página de memoria. La mayoría de los sistemas operativos modernos usan memoria virtual y solo hacen un registro en la tabla de memoria virtual, cuando asigna memoria. Escribir un solo byte en la página de memoria ya obligará al sistema operativo a asignar la página de memoria virtual a la memoria física.
foobar


0

Rubí

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

Simplemente agrega infinitamente (¡recursivo!) Auto-referencias a sí mismo.

Me enteré de esta pequeña joya cuando alguien rompió mi caja de arena Ruby con ella . :RE

Demostración de los aspectos recursivos de la misma:

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

0

C ++ 79

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

No golf

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

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

Arreglé mi entrada para incluir la llamada de main.


Este es un concurso de popularidad. Si el programa funciona, manténgalo como principal y encabezado. está bien. Además, ¿podrías publicar una versión que no sea de golf? Gracias :)
George
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.