Leak Memory in as few bytes as possible

79

15

Your task is to write code that will leak at least one byte of memory in as few bytes as possible. The memory must be leaked not just allocated.

Leaked memory is memory that the program allocates but loses the ability to access before it can deallocate the memory properly. For most high level languages this memory has to be allocated on the heap.

An example in C++ would be the following program:

int main(){new int;}

This makes a new int on the heap without a pointer to it. This memory is instantly leaked because we have no way of accessing it.

Here is what a leak summary from Valgrind might look like:

LEAK SUMMARY:
   definitely lost: 4 bytes in 1 blocks
   indirectly lost: 0 bytes in 0 blocks
     possibly lost: 0 bytes in 0 blocks
   still reachable: 0 bytes in 0 blocks
        suppressed: 0 bytes in 0 blocks

Many languages have a memory debugger (such as Valgrind) if you can you should include output from such a debugger to confirm that you have leaked memory.

The goal is to minimize the number of bytes in your source.

Post Rock Garf Hunter

Posted 2017-02-18T17:34:15.147

Reputation: 55 382

2Perhaps you could have different ranges of amount leaked and depending on how much you leak you lose x% of your byte count – Christopher – 2017-02-18T17:38:07.427

11@ChristopherPeart For one I am not a fan of bonuses on challenges and for two as you have already shown it is very easy to leak unbounded memory. – Post Rock Garf Hunter – 2017-02-18T18:01:51.243

1Related. Not a duplicate, though, because most answers to that question form an infinite reachable structure in memory rather than actually leaking memory. – None – 2017-02-18T18:18:10.740

2what is the idea? That the mem cannot be freed? I guess this would require native execution for garbage collected languages or exploiting bugs. – akostadinov – 2017-02-18T21:26:49.893

What happened to "this is code golf"? – Oliphaunt - reinstate Monica – 2017-02-18T21:45:35.750

I have read only the title of your question and I immediately went to a C++ online compiler to put new int inside the main function! After I've read the question's body, and because the answer is there I will not post that as an answer! – sergiol – 2017-02-19T00:56:58.067

7I see how languages designed for golfing fail miserably on this one ... – Kh40tiK – 2017-02-19T12:25:08.603

DOS batch file, 3 bytes. win :-) – Ray – 2017-02-23T03:24:32.340

1

@Oliphaunt, here it is: https://memegenerator.net/instance/72157724

– aross – 2017-02-23T16:39:00.060

Leaks depend from OS, i would Know if program end, all the memory it is released to the Os, even the one of leaks. The question has one reason if it is requested one function that leak memory... – RosLuP – 2017-06-28T17:15:18.457

I think this is how I justify 16 gigs of RAM for a casual desktop – Stan Strum – 2018-04-08T23:16:43.473

Answers

89

Perl (5.22.2), 0 bytes

Try it online!

I knew there'd be some language out there that leaked memory on an empty program. I was expecting it to be an esolang, but turns out that perl leaks memory on any program. (I'm assuming that this is intentional, because freeing memory if you know you're going to exit anyway just wastes time; as such, the common recommendation nowadays is to just leak any remaining memory once you're in your program's exit routines.)

Verification

$ echo -n | valgrind perl
…snip…
==18517== 
==18517== LEAK SUMMARY:
==18517==    definitely lost: 8,134 bytes in 15 blocks
==18517==    indirectly lost: 154,523 bytes in 713 blocks
==18517==      possibly lost: 0 bytes in 0 blocks
==18517==    still reachable: 0 bytes in 0 blocks
==18517==         suppressed: 0 bytes in 0 blocks
==18517== 
==18517== For counts of detected and suppressed errors, rerun with: -v
==18517== ERROR SUMMARY: 15 errors from 15 contexts (suppressed: 0 from 0)

user62131

Posted 2017-02-18T17:34:15.147

Reputation:

Is there any way to get the valgrind output on TIO? The empty program itself isn't very enlightening :P – CAD97 – 2017-02-19T01:49:24.917

1

@CAD97: Not as far as I know (TIO doesn't have valgrind installed), but the TIO link at least shows what the program's "main" functionality is (i.e. nothing). The links are also generally useful for things like formatting the post, giving a machine-readable version of the program, etc. (although arguably none of that is useful here). The best example of a pointless TIO link is probably this one (which caught a lot of attention at the time).

– None – 2017-02-19T01:53:39.987

I tried installing valgrind earlier, but it requires some permissions the sandbox context doesn't have. – Dennis – 2017-02-19T05:59:22.623

16I liked the Unlambda answer, but this one is (IMHO) too much of a stretch, as it is obviously the interpreter itself which leaks the memory, i.e. I get definitely lost: 7,742 bytes in 14 blocks when I run perl --version on my machine, despite it never gets to running any program, at all. – zeppelin – 2017-02-19T07:14:00.880

11@zeppelin: Agreed, but according to our rules, it's the implementation that defines the language, thus if the implementation leaks memory, all programs in the language leak memory. I'm not necessarily sure I agree with that rule, but at this point it's too entrenched to really be able to change. – None – 2017-02-19T09:03:54.970

8This also works in Node JS. – Dennis – 2017-02-19T18:40:16.763

6This feels like a new standard loophole in the making... – Michael Hampton – 2017-02-22T03:32:40.047

46Finally a Perl script that I can understand. – user11153 – 2017-02-22T16:05:18.247

If Perl one-liners are good, no-liners are better ! – MikeW – 2017-04-12T09:38:52.040

66

C, 48 31 22 bytes

Warning: Don't run this too many times.

Thanks to Dennis for lots of help/ideas!

f(k){shmget(k,1,512);}

This goes one step further. shmget allocates shared memory that isn't deallocated when the program ends. It uses a key to identify the memory, so we use an uninitialized int. This is technically undefined behaviour, but practically it means that we use the value that is just above the top of the stack when this is called. This will get written over the next time that anything is added to the stack, so we will lose the key.


The only case that this doesn't work is if you can figure out what was on the stack before. For an extra 19 bytes you can avoid this problem:

f(){srand(time(0));shmget(rand(),1,512);}

Or, for 26 bytes:

main(k){shmget(&k,1,512);}

But with this one, the memory is leaked after the program exits. While running the program has access to the memory which is against the rules, but after the program terminates we lose access to the key and the memory is still allocated.  This requires address space layout randomisation (ASLR), otherwise &k will always be the same. Nowadays ASLR is typically on by default.


Verification:

You can use ipcs -m to see what shared memory exists on your system. I removed pre-existing entries for clarity:

$ cat leakMem.c 
f(k){shmget(k,1,512);}
int main(){f();}     
$ gcc leakMem.c -o leakMem
leakMem.c:1:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
 f(k){shmget(k,1,512);}
 ^
leakMem.c: In function ‘f’:
leakMem.c:1:1: warning: type of ‘k’ defaults to ‘int’ [-Wimplicit-int]
leakMem.c:1:6: warning: implicit declaration of function ‘shmget’ [-Wimplicit-function-declaration]
 f(k){shmget(k,1,512);}
ppcg:ipcs -m

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      


$ ./leakMem 

$ ipcs -m

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      

0x0000007b 3375157    Riley      0          1          0  

Riley

Posted 2017-02-18T17:34:15.147

Reputation: 11 345

Why is linux not freeing memory when process exits and nothing else is using the memory? I'm sure this scenario is not possible on windows, if there are no handles to shared memory it will get freed, and all the handles are released when process shuts down – Andrew Savinykh – 2017-02-18T21:44:18.893

1@AndrewSavinykh Theoretically, the shmid could have been stored in a file and a program could attach to it in the future. This is how unix shared memory works... – tbodt – 2017-02-18T22:07:11.020

1@AndrewSavinykh Shared memory basically becomes a resource that the OS can give to other processes. It is similar to a file that lives in RAM and any process that knows the name (key) has access to it until it is deleted. Imagine a process that calculates a number and stores it in memory and exits before the process that reads the data connects to the shared memory. In this case, if the OS frees the memory then the second process can't get it. – Riley – 2017-02-18T22:27:07.957

35Thank you for posting this. I just protected TIO against shared memory leaks. – Dennis – 2017-02-18T23:30:06.820

4@Dennis That's why I didn't post a TIO link. I didn't know if it was protected or not. – Riley – 2017-02-18T23:31:54.323

12I like how you use the word problem to describe the scenario where the program leaks less memory than intended. – kasperd – 2017-02-19T14:24:22.347

1

@AndrewSavinykh there are Linux APIs, that were considered OK at the time, but became obsolete with creation of better alternatives and saner development practices. Unlike in Windows, there is no central entity to forcibly declare stuff deprecated, everyone is free to keep using it, even if better alternatives exist. File locks are supplanted by file leases, but some people don't even know those exist; shared memory got replaced by tmpfs, but many still use it by inertia. On the bright side, there is no Vista-like breakage-feasts :)

– user1643723 – 2017-02-19T16:26:23.997

Would f(k){shmget(k,1,512);} work? – Dennis – 2017-02-19T17:44:57.740

1

@Dennis That depends on how strict we are about loosing access. k will often be set to the first argument of the function called before f(). That means that there is a good chance we can figure out what k originally was.

– Riley – 2017-02-19T18:27:08.053

But int k has the same problem, assuming it is one. https://tio.run/nexus/c-gcc#@5@moalQzcWZmVeikG3NxVlQBGSlaSippsTkKekoZGtac9VycaVr5AFVARm5iZl5EA3pGoZGxkBZTqABQDX//wMA Btw, shmget(k,1); seems to work just fine.

– Dennis – 2017-02-19T18:38:41.007

@Dennis If the function modifies it's first argument then k will also change to that. I think that is good enough to loose the key. Thanks! – Riley – 2017-02-19T18:47:48.713

1@Dennis For shmget(k,1);, that doesn't always work for me. Without the third argument of 512 (which is IPC_CREAT) it doesn't always create the new segment. – Riley – 2017-02-19T18:52:23.223

Right, I should have tested it more than once. main(k){shmget(&k,1,512);} should work instead of the rand() approach. – Dennis – 2017-02-19T19:04:06.857

@Dennis After the shmget call we still know what &k is so we still have the key. – Riley – 2017-02-19T19:23:06.287

But that's a full program. How would we recover &k? – Dennis – 2017-02-19T19:23:53.600

@Dennis The question says: "memory that the program allocates but looses the ability to access before it can deallocate ...". The program still has the key so it could deallocate. I'll add it, but keep the rand() one because this is borderline. – Riley – 2017-02-19T19:30:34.233

@AndrewSavinykh you can almost get the same thing with GlobalAddAtom in Windows. Also CreateFileMapping.

But GlobalAddAtom isn't unrecoverable, and neither is CreateFileMapping so I guess they don't really count. – GeirGrusom – 2017-02-20T14:52:10.143

Why does the main method not count towards the bytes? – Thomas Weller – 2017-02-20T22:56:37.760

@ThomasWeller In the verification? Because my submission is just the function. int main(){f();} is there to call f(). In other words, an example of usage. – Riley – 2017-02-20T22:58:19.440

clock() would be much shorter than srand();rand() – None – 2018-08-05T23:16:15.280

40

Unlambda (c-refcnt/unlambda), 1 byte

i

Try it online!

This is really a challenge about finding a pre-existing interpreter which leaks memory on very simple programs. In this case, I used Unlambda. There's more than one official Unlambda interpreter, but c-refcnt is one of the easiest to build, and it has the useful property here that it leaks memory when a program runs successfully. So all I needed to give here was the simplest possible legal Unlambda program, a no-op. (Note that the empty program doesn't work here; the memory is still reachable at the time the interpreter crashes.)

Verification

$ wget ftp://ftp.madore.org/pub/madore/unlambda/unlambda-2.0.0.tar.gz
…snip…
2017-02-18 18:11:08 (975 KB/s) - ‘unlambda-2.0.0.tar.gz’ saved [492894]
$ tar xf unlambda-2.0.0.tar.gz 
$ cd unlambda-2.0.0/c-refcnt/
$ gcc unlambda.c
$ echo -n i | valgrind ./a.out /dev/stdin
…snip…
==3417== LEAK SUMMARY:
==3417==    definitely lost: 40 bytes in 1 blocks
==3417==    indirectly lost: 0 bytes in 0 blocks
==3417==      possibly lost: 0 bytes in 0 blocks
==3417==    still reachable: 0 bytes in 0 blocks
==3417==         suppressed: 0 bytes in 0 blocks
==3417== 
==3417== For counts of detected and suppressed errors, rerun with: -v
==3417== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

user62131

Posted 2017-02-18T17:34:15.147

Reputation:

39

TI-Basic, 12 bytes

While 1
Goto A
End
Lbl A
Pause 

"... a memory leak is where you use a Goto/Lbl within a loop or If conditional (anything that has an End command) to jump out of that control structure before the End command is reached... " (more)

Timtech

Posted 2017-02-18T17:34:15.147

Reputation: 12 038

7Wow, I think I remember this. I kept jumping out of my loops in my old basic programs and noticed how my TI-84+ got slower and slower... – Ray – 2017-02-18T23:07:44.103

2Yep, most of us know the feeling ;) @RayKoopa – Timtech – 2017-02-19T02:44:31.980

13+1 for Ti Basic. I spent most of my 9th grade year programming those things. – markasoftware – 2017-02-19T03:26:14.593

Do you need Pause at the end? You could save 2 bytes. – kamoroso94 – 2017-02-19T05:23:37.593

@kamoroso94 I think so, because "If a program is ended the leak is cleared and will cause no further issues", so it is to stop the program from ending. – Timtech – 2017-02-19T15:24:23.360

A simpler "leak" under these rules would be to create a program named prgmA consisting of the single command prgmA (2 bytes). This creates the same kind of "leak" (technically blowing an internal stack). Neither one is leaking "memory" in the OP's sense, and neither one is "unrecoverable" in OP's sense either (since the While "leak" can be reclaimed by hitting an End, and the infinite recursion can be stopped by... making it not-infinite) — but I don't think the OP's definitions make a whole lot of sense in non-C languages anyway. :) – Quuxplusone – 2017-02-20T08:45:27.383

Nice idea @Quuxplusone, but do notice that in this example there is no recursion and no overflow like there would be with your example. – Timtech – 2017-02-20T18:42:14.027

@Timtech: It's just a question of semantics (as admittedly so was the OP's question). I'd say that in both cases the control flow is looping forever and the internal data structures of the Basic interpreter (in one case the "active programs" stack, in the other case the "active End-able constructs" stack) are growing without bound, so to me there's no difference. In neither case is any "heap memory" allocated; TI-Basic doesn't have that concept. (But see my next comment.) – Quuxplusone – 2017-02-20T19:41:14.290

I'd say the closest thing to a "heap memory allocation" in TI-Basic is 1→L₁(1+len(L₁, and the closest thing to a "leak" is 1→ʟA. If the program does this and then exits, it's up to the calculator user to go delete that newly created list. – Quuxplusone – 2017-02-20T19:45:56.520

32

Python <3.6.5, 23 bytes

property([]).__init__()

property.__init__ leaks references to the property's old fget, fset, fdel, and __doc__ if you call it on an already-initialized property instance. This is a bug, eventually reported as part of CPython issue 31787 and fixed in Python 3.6.5 and Python 3.7.0. (Also, yes, property([]) is a thing you can do.)

user2357112 supports Monica

Posted 2017-02-18T17:34:15.147

Reputation: 1 483

Has a bug report been sent? – mbomb007 – 2018-08-03T14:39:14.673

1

@mbomb007: CPython issue 31787.

– user2357112 supports Monica – 2018-08-03T16:43:03.610

27

C#, 34 bytes

class L{~L(){for(;;)new L();}}

This solution does not require the Heap. It just needs a real hard working GC (Garbage Collector).

Essentially it turns the GC into its own enemy.

Explanation

Whenever the destructor is called, It creates new instances of this evil class as long as the timeout runs out and tells the GC to just ditch that object without waiting for the destructor to finish. By then thousands of new instances have been created.

The "evilness" of this is, the harder the GC is working, the more this will blow up in your face.

Disclaimer: Your GC may be smarter than mine. Other circumstances in the program may cause the GC to ignore the first object or its destructor. In these cases this will not blow up. But in many variations it will. Adding a few bytes here and there might ensure a leak for every possible circumstances. Well except for the power switch maybe.

Test

Here is a test suite:

using System;
using System.Threading;
using System.Diagnostics;
class LeakTest {
    public static void Main() {
        SpawnLeakage();
        Console.WriteLine("{0}-: Objects may be freed now", DateTime.Now);
        // any managed object created in SpawbLeakage 
        //  is no longer accessible
        // The GC should take care of them

        // Now let's see
        MonitorGC();
    }
    public static void SpawnLeakage() {
        Console.WriteLine("{0}-: Creating 'leakage' object", DateTime.Now);
        L l = new L();
    }
    public static void MonitorGC() {
        while(true) {
            int top = Console.CursorTop;
            int left = Console.CursorLeft;
            Console.WriteLine(
                "{0}-: Total managed memory: {1} bytes",
                DateTime.Now,
                GC.GetTotalMemory(false)
            );
            Console.SetCursorPosition(left, top);
        }
    }
}

Output after 10 minutes:

2/19/2017 2:12:18 PM-: Creating 'leakage' object
2/19/2017 2:12:18 PM-: Objects may be freed now
2/19/2017 2:22:36 PM-: Total managed memory: 2684476624 bytes

That's 2 684 476 624 bytes. The Total WorkingSet of the process was about 4.8 GB

This answer has been inspired by Eric Lippert's wonderful article: When everything you know is wrong.

MrPaulch

Posted 2017-02-18T17:34:15.147

Reputation: 771

This is fascinating. Does the garbage collector "Forget" that some things exist and lose track of them because of this? I dont know much about c#. Also now I am wondering, what is the difference between a bomb and a leak? I imagine a similar fiasco could be created by calling a constructor from inside of a constructor, or having an infinite recursing function that never stops, although technically the system never loses track of those references, it just runs out of space... – don bright – 2017-02-20T00:50:13.773

1A constructor within a constructor would cause a stack overflow. But the destructor of an instance gets called in a flat hierarchy. The GC actually never loses track of the objects. Just whenever it tries to destroy them it unwittingly create new objects. User code on the other hand has no access to said objects. Also the mentioned inconsistencies may arise since the GC may decide to destroy an object without calling its destructor. – MrPaulch – 2017-02-20T07:01:50.913

Wouldn't the challenge be complete by just using class L{~L(){new L();}}? AFAIK the for(;;) only makes it leak memory faster, right? – BgrWorker – 2017-02-20T08:05:51.507

1Sadly, no. Since for each destroyed object only one new instance is going to be created, which then again is inaccessible and marked for destruction. Repeat. Only ever one object will be pending for destruction. No increasing population. – MrPaulch – 2017-02-20T08:09:57.793

@MrPaulch well, the challenge only asks you to leak one byte, and according to the very interesting article you linked at the bottom, when the program ends finalizers will eventually timeout and the last created object will remain allocated. – BgrWorker – 2017-02-20T08:22:56.123

2Not really. Eventually one finalized will be ignored. The corresponding object will be eaten regardless. – MrPaulch – 2017-02-20T08:24:16.900

Thanks that is very interesting situation with garbage collection in c#! – don bright – 2017-02-20T13:59:25.990

How does this work if L is never instantiated in the first place? – LegionMammal978 – 2017-02-23T12:40:29.863

It doesn't. It also doesn't work if you don't start the process. Sarcasm aside: the challenge asked for some code that can be executed that leaks. In this case instantiating L is the equivalent of running a process or calling a function. – MrPaulch – 2017-02-23T12:43:51.897

26

C (gcc), 15 bytes

f(){malloc(1);}

Verification

$ cat leak.c
f(){malloc(1);}
main(){f();}
$ gcc -g -o leak leak.c
leak.c: In function ‘f’:
leak.c:1:5: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
 f(){malloc(1);}
     ^
$ valgrind --leak-check=full ./leak
==32091== Memcheck, a memory error detector
==32091== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==32091== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==32091== Command: ./leak
==32091==
==32091==
==32091== HEAP SUMMARY:
==32091==     in use at exit: 1 bytes in 1 blocks
==32091==   total heap usage: 1 allocs, 0 frees, 1 bytes allocated
==32091==
==32091== 1 bytes in 1 blocks are definitely lost in loss record 1 of 1
==32091==    at 0x4C29110: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==32091==    by 0x40056A: f (leak.c:1)
==32091==    by 0x40057A: main (leak.c:2)
==32091==
==32091== LEAK SUMMARY:
==32091==    definitely lost: 1 bytes in 1 blocks
==32091==    indirectly lost: 0 bytes in 0 blocks
==32091==      possibly lost: 0 bytes in 0 blocks
==32091==    still reachable: 0 bytes in 0 blocks
==32091==         suppressed: 0 bytes in 0 blocks
==32091==
==32091== For counts of detected and suppressed errors, rerun with: -v
==32091== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Dennis

Posted 2017-02-18T17:34:15.147

Reputation: 196 637

26

Javascript, 14 bytes

Golfed

setInterval(0)

Registers an empty interval handler with a default delay, discarding the resulting timer id (making it impossible to cancel).

enter image description here

I've used a non-default interval, to create several million timers, to illustrate the leak, as using a default interval eats CPU like mad.

zeppelin

Posted 2017-02-18T17:34:15.147

Reputation: 7 884

5Haha I love that you've typed 'Golfed', makes me curious about the ungolfed version – Martijn – 2017-02-20T15:18:14.803

9it might look like this if(window && window.setInterval && typeof window.setInterval === 'function') { window.setInterval(0); } – Tschallacka – 2017-02-20T15:51:08.810

@Martijn Believe it or not, but I actually did golfed it a bit :) The proper syntax for setInterval is setInterval(func|string, delay[, param1, param2, ...]);, and both func and delay are required parameters, so setInterval(0) abuses them both. – zeppelin – 2017-02-20T16:02:03.023

3Actually, this is not impossible to cancel: interval (and timeout) ID's are numbered sequentially, so it's fairly easy to cancel the thing just by calling clearInterval with an incrementing ID until your interval is gone. For example: for(let i=0;i<1e5;i++){try{clearInterval(i);}catch(ex){}} – user2428118 – 2017-02-20T22:40:02.450

Not wholly unreachable: The interval id can be guessed in multiple ways: Just plain brute force: for (var i = 0; i++; i<100) { clearInterval(i) }, or more 'elegantly': var i = setInterval(); clearInterval(i); clearInterval(i-1) since it is just an incremented integer. – Wizek – 2017-02-20T22:40:22.027

@user2428118

Brute-forcing the timer ID, might indeed work, in some implementations.

But in general the order and range of ID values is not guaranteed, as well if they will be reused or not (most implementations specify the ID to be an opaque numeric token).

So, I don't think there is a "legitimate" way to cancel timers w/o knowing the ID.

Anyway, finding a "leak", which can not be "hacked" or "brute-forced" is (IMHO) not the point of this challenge, e.g. most malloc-based answers can be "fixed" with the malloc hooks, pretty easily, but that does not disqualify them. – zeppelin – 2017-02-21T08:58:37.387

5@user2428118 As zeppelin says, this is no more "legitmate" than saying the C/C++ leaks aren't "real" because you could brute force calls to free() – TripeHound – 2017-02-21T12:03:36.573

1Wow, not many challenges where JavaScript is an actual contender... – Jared Smith – 2017-02-21T18:49:54.240

1@zeppelin user2428118 only disputed your claim that it's impossible to cancel, without saying anything about whether it should count as a leak. Yes, it's possible to cancel the interval. Yes, it's a leak and a valid answer nonetheless. Just change the "making it impossible to cancel" to something like "making it impossible to cancel without guessing the id" to correct that one small inaccuracy. – hvd – 2017-02-25T16:24:14.323

Would a pair of backticks (template string) instead of (0) or even setInterval() work, too? – user42589 – 2017-02-28T23:51:30.543

19

Java, 10 bytes

Finally, a competitive answer in Java !

Golfed

". "::trim

This is a method reference (against a string constant), which can be used like that:

Supplier<String> r = ". "::trim

A literal string ". " will be automatically added to the global interned strings pool, as maintained by the java.lang.String class, and as we immediatelly trim it, the reference to it can not be reused further in the code (unless you declare exactly the same string again).

...

A pool of strings, initially empty, is maintained privately by the class String.

All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of the The Java™ Language Specification.

...

https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#intern--

You can turn this in a "production grade" memory leak, by adding the string to itself and then invoking the intern() method explicitly, in a loop.

zeppelin

Posted 2017-02-18T17:34:15.147

Reputation: 7 884

2I considered this for C#... but I don't think it counts, because as you say you can access that memory by including another string literal. I'd also be interested to know what ("." + " ").intern() would do (if they were user input or w/e, so we discount compiler optimisations). – VisualMelon – 2017-02-19T09:02:50.147

@VisualMelon - the reference is lost, so you have to recreate the string content exactly, to be able to access it again, which is pretty much impossible to do programmatically. – zeppelin – 2017-02-19T09:14:49.597

Surly it's just a case of adding two strings together, as in my prior comment, or does intern not work like that? It's perfectly possible, I would say. This answer also is neither a program, nor a self-contained piece of code that leaks memory, as I don't believe it will compile by itself (it has to have some type-asserting context) – VisualMelon – 2017-02-19T09:19:59.640

Yep, if happen to know the string content in advance, which is an "external" piece of information. I.e. consider this is a library function and you do not see the source. – zeppelin – 2017-02-19T09:26:47.090

ockquote>

it has to have some type-asserting context

I don't think there is a good consensus on Java lambdas currently, and there are well-accepted Java-lambda answers around, which do not provide any explicit type information.

But anyway, in this specific case it is not just a lambda, but an object method reference, against the string literal (which only possible type is a concrete final class java.lang.String), pointing to the 0-arg trim() method of it, making it pretty unambiguous. – zeppelin – 2017-02-19T17:52:04.003

1Indeed, the only consensus is slim at best, I'm just firmly on the "the code should compile" side. I'm still not sure I buy this solution given the wording on the question (these strings can't be freed, and they can be found in normal operating code even though it's unlikely), but I invite others to make their own judgement – VisualMelon – 2017-02-19T18:32:46.237

Forgive me for saying, I think this is ridiculous. You could just as well say that every cache is a memory leak. The java GC won't clear this memory since it is intentionally reserved for performance reasons - to allow == comparisons (which, anyway, is not entirely true, since interned Strings are weakly-referenced). – Elist – 2017-02-19T19:00:04.390

1ockquote>

You could just as well say that every cache is a memory leak

Exactly, if a) What you put into it does not expire by itself b) There is no way to explicitly remove anything from it, or enumerate it's content c) You have lost the key. Now you have a piece of memory allocated for something you can not access or remove any longer, hence it is a leak.

And I don't think interned string literals are subject to garbage collection, even in implementations which do GC on the interned strings pool per-se. – zeppelin – 2017-02-19T19:37:00.180

3That string isn't even inaccessible, let alone leaked. We can retrieve it at any time by interning an equal string. If this were to count, any unused global variable (private static in Java) would be a leak. That's not how memory leaks are defined. – user2357112 supports Monica – 2017-02-20T01:00:19.127

3@user2357112 "...That string isn't even inaccessible..." That only looks obvious because you see the code. Now consider you got this method reference X() as an argument to your code, you know that it allocates (and interns) a string literal inside, but you do not know which one exactly, it might be ". " or "123" or any other string of a (generally) unknown length. Would you please demonstrate how you can still access it, or deallocate the entry in the "intern" pool it occupies? – zeppelin – 2017-02-20T09:40:07.557

One thing I don't really know how it has to been handled: you can't use this exactly code and run it through javac. So are java answers always (like C# or other languages with that buildup) with all that class and "public static void main" part. – Serverfrog – 2017-02-20T10:02:41.920

@Serverfrog, I don't think there is a good consensus about it, really. There are well-accepted lambda-based answers (like this one), which do not include all this repeated boilerplate code. Moreover, the method reference, as used in this answer, points to a concrete method of a final class (i.e. it implies more type information than a generic lambda). But I guess that would make a good topic to discuss on Meta.

– zeppelin – 2017-02-20T10:34:37.393

@zeppelin You used a specific String, not a random one. So we have access to the code and we can show you that that code isn't unreachable. It isn't a leak. Your best bet if you want to use the string cache is to generate a random String with an unspecified seed and .intern() it. so we can't go back to access the String again. Using any specific String will make it accessible again. – Olivier Grégoire – 2017-02-20T11:39:47.097

@zeppelin: A memory leak is not when it's unlikely or difficult to reach an object. We can access this string simply by guessing correctly. That's not a leak. (If guessing is somehow a magical superability that doesn't count, we can open and read the .class file, even within the program, and there's probably some way to use reflection to determine the string's contents too.) – user2357112 supports Monica – 2017-02-20T15:27:35.167

@Serverfrog functions are permitted, including lambdas. It is a good idea to include code to invoke the function or explain which functional interface can wrap the lambda, which this answer did. For golfing purposes, however, only the lambda is included in the byte count - not any other "glue" code to include it in a larger program. – None – 2017-02-20T15:41:10.843

2@user2357112 On a machine with a finite memory, you can access a value stored in any piece of memory simply by guessing it correctly, but that does not mean that such a thing as memory leaks do not exist. there's probably some way to use reflection to determine the string's contents too could you demonstrate this ? (hint, String.intern() is implemented in the native code). – zeppelin – 2017-02-20T15:44:17.690

Won't Java garbage collect the original string, thus not making this a memory leak? – tenmiles – 2017-02-22T13:30:18.330

1@tenmiles - it is a string literal, so it should not be garbage collected. – zeppelin – 2017-02-22T13:31:17.810

1Personally I like this answer. However I think the best argument against it is that the GC does clean up interned Strings in newer versions (7+) of java. Interned Strings used to be allocated in PermGen but were moved to the heap as of Java 7. Furthermore I think we need better clarification about what a "memory leak" is. The argument I'm seeing is that we can still get a reference to the leaked String. I don't think this matters because we would still have a failure to release that memory even though it's reachable. Failure to release vs lost reference. – Poke – 2017-02-23T14:31:43.170

@Poke - that is true for the dynamically allocated strings in Java 7+ (at least for the HotSpot family of VMs), but a string literal, as used in this answer, won't be garbage collected (as well as it's entry in the intern pool).

– zeppelin – 2017-02-23T16:47:26.797

17

Rust, 52 bytes

extern{fn malloc(_:u8);}fn main(){unsafe{malloc(9)}}

Allocates some bytes with the system malloc. This assumes the wrong ABI is acceptable.


Rust (in theory), 38 bytes

fn main(){Box::into_raw(Box::new(1));}

We allocate memory on the heap, extract a raw pointer, and then just ignore it, effectively leaking it. (Box::into_raw is shorter then std::mem::forget).

However, Rust by default uses jemalloc, which valgrind can't detect any leakage. We could switch to the system allocator but that adds 50 bytes and requires nightly. Thanks so much for memory safety.


Output of the first program:

==10228== Memcheck, a memory error detector
==10228== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==10228== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==10228== Command: ./1
==10228== 
==10228== 
==10228== HEAP SUMMARY:
==10228==     in use at exit: 9 bytes in 1 blocks
==10228==   total heap usage: 7 allocs, 6 frees, 2,009 bytes allocated
==10228== 
==10228== LEAK SUMMARY:
==10228==    definitely lost: 9 bytes in 1 blocks
==10228==    indirectly lost: 0 bytes in 0 blocks
==10228==      possibly lost: 0 bytes in 0 blocks
==10228==    still reachable: 0 bytes in 0 blocks
==10228==         suppressed: 0 bytes in 0 blocks
==10228== Rerun with --leak-check=full to see details of leaked memory
==10228== 
==10228== For counts of detected and suppressed errors, rerun with: -v
==10228== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

kennytm

Posted 2017-02-18T17:34:15.147

Reputation: 6 847

awesome. posts like this led me to explore Rust over the past year, definitely one of the most fun languages i have tried to learn. – don bright – 2019-03-04T01:54:48.313

16

8086 ASM, 3 bytes

This examples assumes that a C runtime is linked in.

jmp _malloc

this assembles to e9 XX XX where XX XX is the relative address of _malloc

This invokes malloc to allocate an unpredictable amount of memory and then immediately returns, terminating the processes. On some operating systems like DOS, the memory might not be reclaimable at all until the system is rebooted!

FUZxxl

Posted 2017-02-18T17:34:15.147

Reputation: 9 656

The normal implementation of malloc will result in memory being freed on process exit. – Joshua – 2017-11-17T00:00:05.317

@Joshua Yeah, but that's implementation defined behaviour. – FUZxxl – 2017-11-17T00:03:14.533

12

Forth, 6 bytes

Golfed

s" " *

Allocates an empty string with s" ", leaving it's address and length (0) on the stack, then multiplies them (resulting in a memory address being lost).

Valgrind

%valgrind --leak-check=full gforth -e 's" " * bye'
...
==12788== HEAP SUMMARY:
==12788==     in use at exit: 223,855 bytes in 3,129 blocks
==12788==   total heap usage: 7,289 allocs, 4,160 frees, 552,500 bytes allocated
==12788== 
==12788== 1 bytes in 1 blocks are definitely lost in loss record 1 of 22
==12788==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12788==    by 0x406E39: gforth_engine (in /usr/bin/gforth-0.7.0)
==12788==    by 0x41156A: gforth_go (in /usr/bin/gforth-0.7.0)
==12788==    by 0x403F9A: main (in /usr/bin/gforth-0.7.0)
==12788== 
...
==12818== LEAK SUMMARY:
==12818==    definitely lost: 1 bytes in 1 blocks
==12818==    indirectly lost: 0 bytes in 0 blocks

zeppelin

Posted 2017-02-18T17:34:15.147

Reputation: 7 884

10

go 45 bytes

package main
func main(){go func(){for{}}()}

this creates an anonymous goroutine with an infinite loop inside of it. the program can continue to run as normal, as starting the goroutine is kind of like spawning a concurrently running small thread, but the program has no way to reclaim the memory that was allocated for the goroutine. the garbage collector will never collect it either since it is still running. some people call this 'leaking a goroutine'

don bright

Posted 2017-02-18T17:34:15.147

Reputation: 1 189

golf check: this is 2 bytes shorter than calling C.malloc(8), since you need to import"C" – Riking – 2017-03-01T00:44:26.853

9

Java 1.3, 23 bytes

void l(){new Thread();}

Creating a thread but not starting it. The thread is registered in the internal thread pool, but will never be started, so never ended and therefore never be a candidate for the GC. It is an unretrievable object, stuck in Java limbos.

It's a bug in Java until 1.3 included as it was fixed afterwards.

Testing

The following program makes sure to pollute the memory with new thread objects and show a decreasing free memory space. For the sake of leaks testing, I intensively makes the GC run.

public class Pcg110485 {

    static
    void l(){new Thread();}

    public static void main(String[] args) {

        while(true){
            l();
            System.gc();
            System.out.println(Runtime.getRuntime().freeMemory());
        }
    }
}

Olivier Grégoire

Posted 2017-02-18T17:34:15.147

Reputation: 10 647

Since this works only on specific Java versions, you should say "Java 3" in your header instead. – None – 2017-02-20T15:43:50.663

5There's no such thing as Java 3. It's Java 1.3. There was Java 1.0, 1.1, 2, 1.3, 1.4, 5, 6, 7, 8, 9. Weird numbering, but that's how it is. – Olivier Grégoire – 2017-02-21T01:54:47.200

This was my idea too. Damn. – Magic Octopus Urn – 2017-06-28T19:12:24.553

8

Swift 3, 38 bytes

New version:

class X{var x: X!};do{let x=X();x.x=x}

x has a strong reference to itself, so it will not be deallocated, leading to a memory leak.

Old version:

class X{var y:Y!}
class Y{var x:X!}
do{let x=X();let y=Y();x.y=y;y.x=x}

x contains a strong reference to y, and vice versa. Thus, neither will be deallocated, leading to a memory leak.

Daniel

Posted 2017-02-18T17:34:15.147

Reputation: 6 425

Hmm, you still can reference that memory through x and y, so this does not really look like a leak to me (unless you destroy them somehow). – zeppelin – 2017-02-19T06:19:03.573

@zeppelin The last line could be wrapped in a function to fix that – NobodyNada - Reinstate Monica – 2017-02-19T18:51:19.533

@NobodyNada, if I were to put the last line in a do block that would fix the problem zeppelin raised right? – Daniel – 2017-02-19T19:04:07.873

@Dopapp Yeah; a do would work as well. Good idea! – NobodyNada - Reinstate Monica – 2017-02-19T19:17:12.007

It can be shortened, you don't need two classes - X can hold reference to itself: class X{var x: X!};do{let x=X();x.x=x} – Sebastian Osiński – 2017-02-20T18:59:11.637

@SebastianOsiński, oh yes I didn't think of that! – Daniel – 2017-02-20T20:33:17.160

@Dopapp It's nice to see a Swift answer :) I submitted one, myself: http://codegolf.stackexchange.com/a/111013/11490

– Alexander - Reinstate Monica – 2017-02-23T06:30:32.060

8

Befunge (fungi), 1 byte

$

This may be platform dependent and version dependent (I've only tested with version 1.0.4 on Windows), but fungi has historically been a very leaky interpreter. The $ (drop) command shouldn't do anything on an empty stack, but looping over this code somehow manages to leak a lot of memory very quickly. Within a matter of seconds it will have used up a couple of gigs and will crash with an "out of memory" error.

Note that it doesn't necessarily have to be a $ command - just about anything would do. It won't work with a blank source file though. There's got to be at least one operation.

James Holderness

Posted 2017-02-18T17:34:15.147

Reputation: 8 298

7

Delphi (Object Pascal) - 33 bytes

Creating an object without a variable, full console program:

program;begin TObject.Create;end.

Enabling FastMM4 in the project will show the memory leak:

enter image description here

R-D

Posted 2017-02-18T17:34:15.147

Reputation: 231

6

C# - 84bytes

class P{static void Main(){System.Runtime.InteropServices.Marshal.AllocHGlobal(1);}}

This allocates exactly 1 byte of unmanaged memory, and then loses the IntPtr, which I believe is the only way to get at or free it. You can test it by stuffing it in a loop, and waiting for the application to crash (might want to add a few zeros to speed things up).

I considered System.IO.File.Create("a"); and such, but I'm not convinced that these are necessarily memory leaks, as the application itself will collect the memory, it's the OS underneath that might leak (because Close or Dispose were not called). File access stuff also requires file system permissions, and no one wants to rely on those. And it turns out this won't leak anyway, because there is nothing stopping the finaliser being called (which does free the underlying resources is possible), which the framework includes to mitigate these sorts of error of judgement (to some degree), and to confuse programmers with seemingly non-deterministic file locking (if you're a cynic). Thanks to Jon Hanna for putting me straight on this.

I am a tad disappointed that I can't find a shorter way. The .NET GC works, I can't think of any IDisposables in mscorlib that will definitely leak (and indeed they all seem to have finalisers, how annoying), I'm not aware of any other way to allocate unmanaged memory (short of PInvoke), and reflection ensures anything with a reference to it (regardless of language semantics (e.g. private members or classes with no accessors)) can be found.

VisualMelon

Posted 2017-02-18T17:34:15.147

Reputation: 3 810

1System.IO.File.Create("a") won't leak anything, but GC.SuppressFinalize(System.IO.File.Create("a")) will as it is explicitly asked not to run the finaliser of the FileStream produced. – Jon Hanna – 2017-02-19T03:13:31.657

@JonHanna quite right. My IDisposable paranoia seems to have got the better of me. – VisualMelon – 2017-02-19T08:40:41.267

You might have a chance to make GDI+ leak using System.Drawing.Bitmap. Don't know if it counts because it's a windows library causing the leak, not the program itself. – BgrWorker – 2017-02-20T07:42:35.280

@BgrWorker they no doubt have a finaliser also, and I tend to avoid external libraries in code-golf because I don't agree with the consensus on costing them: if you can find a way you're confident in, feel free to post it in your own answer! – VisualMelon – 2017-02-20T17:45:58.913

<!-- language: lang-c# --> Thanks for this & nice answer! (It's C# so I love it) – Metoniem – 2017-02-22T13:50:41.073

@Metoniem I think you may have commented on the wrong answer ;) You can suggest the language clause as an edit to MrPlauch's C# answer. – VisualMelon – 2017-02-22T17:08:21.917

@VisualMelon to be fair my answer stretches the bounds of this challenge. Since it is not a classic memory leak. It is more like turning the entity responsible for avoiding leaks into ... exploding. As a result it "leaks". Your answer however is the "real" memory leak, as implemented in C# – MrPaulch – 2017-02-22T22:40:29.060

5

Factor, 13 bytes

Factor has automatic memory management, but also gives access to some libc functionality:

1 malloc drop

Manually allocates 1 byte of memory, returns it's address, and drops it.

malloc actually registers a copy to keep track of memory leaks adn double frees, but identifying the one you leaked is not an easy task.

If you prefer to make sure you really lose that reference:

1 (malloc) drop

Testing leaks with [ 1 malloc drop ] leaks. says:

| Disposable class | Instances |                    |
| malloc-ptr       | 1         | [ List instances ] |

Testing leaks with [ 1 (malloc) drop ] leaks. says:

| Disposable class | Instances | |

Oh no! Poor factor, it's got Alzheimer now! D:

fede s.

Posted 2017-02-18T17:34:15.147

Reputation: 945

4

AutoIt, 39 bytes

#include<Memory.au3>
_MemGlobalAlloc(1)

Allocates one byte from the heap. Since the handle returned by _MemGlobalAlloc is discarded, there is no way to explicitly free that allocation.

mınxomaτ

Posted 2017-02-18T17:34:15.147

Reputation: 7 398

4

Common Lisp (SBCL only), 28 26 bytes

sb-alien::(make-alien int)

You run it like so: sbcl --eval 'sb-alien::(make-alien int)'; nothing is printed nor returned, but the memory allocation happens. If I wrap the form inside a (print ...), the pointer is displayed in the REPL.

  1. package::(form) is a special notation in SBCL for temporarily binding the current package while reading a form. This is used here to avoid prefixing both make-alien and int with sb-alien. I think it would be cheating to assume the current package is set to this one, because that's not the case at startup.

  2. make-alien allocates memory for a given type and an optional size (using malloc).

  3. When executing this in the REPL, add 0 after the allocation so that the REPL does not return the pointer, but that value instead. Otherwise, that would no be a real leak because the REPL remembers the last three returned values (See *, **, ***) and we could still have a chance to free the allocated memory.

2 bytes removed thanks to PrzemysławP, thanks!

coredump

Posted 2017-02-18T17:34:15.147

Reputation: 6 292

1Can't you use 1 (or 2, 3, etc.) instead of () so that you return value 1? It would save 1 byte. Also is this answer REPL only? Maybe if you load code with load you can not include () or anything at the end, because it will not be accessible anyway? – None – 2017-11-29T23:20:28.363

1@PrzemysławP You are right on both points, I tried with eval and this works as you said. Thanks a lot! – coredump – 2017-11-30T08:42:39.733

3

Java (OpenJDK 9), 322 220 bytes

import sun.misc.*;class Main{static void main(String[]a)throws Exception{java.lang.reflect.Field f=Unsafe.class.getDeclaredField("theUnsafe");f.setAccessible‌​(1<2);((Unsafe)f.get‌​(1)).allocateMemory(‌​1);}}

Try it online!

This is a other Memory leak that don't use the String Cache. It Allocates half of your RAM and you can't do anything with it.

Thanks to zeppelin for saving all the bytes

Serverfrog

Posted 2017-02-18T17:34:15.147

Reputation: 245

You can save a bunch of bytes by obtaining the Unsafe instance from the static variable inside it, like that: import sun.misc.*;class M{static void main(String[]a)throws Exception{java.lang.reflect.Field f=Unsafe.class.getDeclaredField("theUnsafe");f.setAccessible(1<2);((Unsafe)f.get(1)).allocateMemory(1);}} – zeppelin – 2017-02-20T10:23:26.023

And you can save some more by replacing the public static void main by a static initializer static{try{}catch(Exception e){}} (which could be a bit more tricky to launch but is nevertheless valid and compilable). – zeppelin – 2017-02-20T10:25:58.470

yhea the use of the constructor was used in a Android version of code I used. I will change some things when im @home but I will go the path you went with a single statement ;) – Serverfrog – 2017-02-20T17:42:01.297

true can be replaced with 1>0 – masterX244 – 2017-02-23T14:51:03.593

3

C++, 16 bytes

main(){new int;}

I don't have valgrind to check it leaks, but pretty sure it should. Otherwise I would try:

main(){[]{new int;}();}

Valgrind result

(It does leak indeed)

==708== LEAK SUMMARY:
==708==    definitely lost: 4 bytes in 1 blocks

matovitch

Posted 2017-02-18T17:34:15.147

Reputation: 131

@WheatWizard I am using g++ 4.3.2 (not the most recent one) and it compiles just fine. No return type is int by default I think. With -Wall I have a warning though: plop.cpp:1: warning: ISO C++ forbids declaration of 'main' with no type – matovitch – 2017-02-20T15:54:53.147

2@WheatWizard Sorry, I just saw you gave the c++ example to start the contest. Coming from reddit I only looked at the answers and (strangely) did not saw any C++. I feel a bit dumb. :/ – matovitch – 2017-02-20T16:19:10.463

Consensus is that you can count just []{new int;} as a C++ function (the challenge didn't specify a whole program). – Toby Speight – 2018-08-03T11:39:13.360

3

c, 9 bytes

main(){}

Proof:

localhost/home/elronnd-10061: cat t.c
main(){}
localhost/home/elronnd-10062: valgrind gcc t.c
==10092== Memcheck, a memory error detector
==10092== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==10092== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==10092== Command: gcc t.c
==10092==
t.c:1:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
 main(){}
 ^~~~
==10092==
==10092== HEAP SUMMARY:
==10092==     in use at exit: 178,518 bytes in 73 blocks
==10092==   total heap usage: 362 allocs, 289 frees, 230,415 bytes allocated
==10092==
==10092== LEAK SUMMARY:
==10092==    definitely lost: 4,659 bytes in 8 blocks
==10092==    indirectly lost: 82 bytes in 5 blocks
==10092==      possibly lost: 0 bytes in 0 blocks
==10092==    still reachable: 173,777 bytes in 60 blocks
==10092==         suppressed: 0 bytes in 0 blocks
==10092== Rerun with --leak-check=full to see details of leaked memory
==10092==
==10092== For counts of detected and suppressed errors, rerun with: -v
==10092== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Elronnd

Posted 2017-02-18T17:34:15.147

Reputation: 101

1You're not actually leaking memory; gcc is. This should also work with the empty program. Try gcc src.c && valgrind ./a.out, which should produce a clean result. – None – 2018-10-29T20:20:11.793

3

C#, 109 bytes

public class P{static void Main({for(;;)System.Xml.Serialization.XmlSerializer.FromTypes(new[]{typeof(P)});}}

We found the idea behind this leak in production code and researching it leads to this article. The main problem is in this long quote from the article (read it for more info):

Searching my code for PurchaseOrder, I find this line of code in page_load of one of my pages XmlSerializer serializer = new XmlSerializer(typeof(PurchaseOrder), new XmlRootAttribute(“”));

This would seem like a pretty innocent piece of code. We create an XMLSerializer for PurchaseOrder. But what happens under the covers?

If we take a look at the XmlSerializer constructor with Reflector we find that it calls this.tempAssembly = XmlSerializer.GenerateTempAssembly(this.mapping, type, defaultNamespace, location, evidence); which generates a temp (dynamic) assembly. So every time this code runs (i.e. every time the page is hit) it will generate a new assembly.

The reason it generates an assembly is that it needs to generate functions for serializing and deserializing and these need to reside somewhere.

Ok, fine… it creates an assembly, so what? When we’re done with it, it should just disappear right?

Well… an assembly is not an object on the GC Heap, the GC is really unaware of assemblies, so it won’t get garbage collected. The only way to get rid of assemblies in 1.0 and 1.1 is to unload the app domain in which it resides.

And therein lies the problem Dr Watson.

Running from the compiler in Visual Studio 2015 and using the Diagnostic Tools Window shows the following results after about 38 seconds. Note the Process memory is steadily climbing and the Garbage Collector (GC) keeps running but can't collect anything.

Diagnostic Tools Window

TheLethalCoder

Posted 2017-02-18T17:34:15.147

Reputation: 6 930

2

C 30 bytes

f(){int *i=malloc(sizeof(4));}

Valgrind Results:

         ==26311== HEAP SUMMARY:
         ==26311==     in use at exit: 4 bytes in 1 blocks
         ==26311==   total heap usage: 1 allocs, 0 frees, 4 bytes allocated
         ==26311== 
         ==26311== LEAK SUMMARY:
         ==26311==    definitely lost: 4 bytes in 1 blocks
         ==26311==    indirectly lost: 0 bytes in 0 blocks
         ==26311==      possibly lost: 0 bytes in 0 blocks
         ==26311==    still reachable: 0 bytes in 0 blocks
         ==26311==         suppressed: 0 bytes in 0 blocks
         ==26311== Rerun with --leak-check=full to see details of leaked memory

Abel Tom

Posted 2017-02-18T17:34:15.147

Reputation: 1 150

2Is it possible to instead just do main(){malloc(1);}? – kirbyfan64sos – 2017-02-20T18:46:24.463

@Yea it is! But its already been posted! – Abel Tom – 2017-02-20T18:52:06.553

2

Dart, 76 bytes

import'dart:async';main()=>new Stream.periodic(Duration.ZERO).listen((_){});

A bit like the JavaScript answer. When you call .listen on a Dart stream object you are given back a StreamSubscription, which allows you to disconnect from the stream. However, if you throw that away, you can never unsubscribe from the stream, causing a leak. The only way the leak can be fixed is if the Stream itself gets collected, but its still referenced internally by a StreamController+Timer combo.

Unfortunately, Dart is too smart for the other stuff I've tried. ()async=>await new Completer().future doesn't work because using await is the same as doing new Completer().future.then(<continuation>), which allows the closure itself to be destroyed the second Completer isn't referenced (Completer holds a reference to the Future from .future, Future holds a reference to the continuation as a closure).

Also, Isolates (aka threads) are cleaned up by GC, so spawning yourself in a new thread and immediately pausing it (import'dart:isolate';main(_)=>Isolate.spawn(main,0,paused:true);) doesn't work. Even spawning an Isolate with an infinite loop (import'dart:isolate';f(_){while(true){print('x');}}main()=>Isolate.spawn(f,0);) kills the Isolate and exits the program.

Oh well.

Dwayne Slater

Posted 2017-02-18T17:34:15.147

Reputation: 111

if your main program kept running and doing other stuff, would the garbage collector ever be able to stop the isolate? i ask because my goroutine example sounds similar... i assumed that the fact that the program exits and gives all memory back to the OS doesn't necessarily mean it hasn't leaked. – don bright – 2017-02-21T05:06:20.567

2

Swift, 12 bytes

[3,5][0...0]

Explanation:

This is a de-facto memory leak that can occur in any language, regardless if the language uses memory manual management, automated reference counting (ARC, like Swift), or even sweeping garbage collection.

[3,5] is just an array literal. This array allocates enough memory for at least these those 2 elements. The 3 and 5 are just arbitrary.

Subscripting (indexing) an Array<T> produces an ArraySlice<T>. An ArraySlice<T> is a view into the memory of the Array it was created from.

[3,5][0...0] produces an ArraySlice<Int>, whose value is [3]. Note that the 3 in this slice is the same 3 element as the 3 in the original Array shown above, not a copy.

The resulting slice can then be stored into a variable and used. The original array is no longer referenced, so you would think it could be deallocated. However, it cannot.

Since the slice exposes a view onto the memory of the array it came from, the original array must be kept alive as long as the slice lives. So of the original 2 element-sizes worth of memory that were allocated, only first element-size worth of memory is being used, with the other the one being required to exist so as to not allocate the first. The second element-size of memory is de-factor leaked.

The solution to this problem is to not keep alive small slices of large arrays for long. If you need to persist the slice contents, then promote it to an Array, which will trigger the memory to be copied, thus removing the dependancy on the original array's memory:

Array([3,5][0...0])

Alexander - Reinstate Monica

Posted 2017-02-18T17:34:15.147

Reputation: 481

2

Solution 1: C (Mac OS X x86_64), 109 bytes

The source for golf_sol1.c

main[]={142510920,2336753547,3505849471,284148040,2370322315,2314740852,1351437506,1208291319,914962059,195};

The above program needs to be compiled with execution access on the __DATA segment.

clang golf_sol1.c -o golf_sol1 -Xlinker -segprot -Xlinker __DATA -Xlinker rwx -Xlinker rwx

Then to execute the program run the following:

./golf_sol1 $(ruby -e 'puts "\xf5\xff\xff\xfe\xff\xff\x44\x82\x57\x7d\xff\x7f"')

Results:

Unfortunately Valgrind does not watch for memory allocated from system calls, so I can't show a nice detected leak.

However we can look at vmmap to see the large chunk of allocated memory (MALLOC metadata).

                                VIRTUAL   REGION 
REGION TYPE                        SIZE    COUNT (non-coalesced) 
===========                     =======  ======= 
Kernel Alloc Once                    4K        2 
MALLOC guard page                   16K        4 
MALLOC metadata                   16.2M        7 
MALLOC_SMALL                      8192K        2         see MALLOC ZONE table below
MALLOC_TINY                       1024K        2         see MALLOC ZONE table below
STACK GUARD                       56.0M        2 
Stack                             8192K        3 
VM_ALLOCATE (reserved)             520K        3         reserved VM address space (unallocated)
__DATA                             684K       42 
__LINKEDIT                        70.8M        4 
__TEXT                            5960K       44 
shared memory                        8K        3 
===========                     =======  ======= 
TOTAL                            167.0M      106 
TOTAL, minus reserved VM space   166.5M      106 

Explanation

So I think I need to describe what's actually going on here, before moving onto the improved solution.

This main function is abusing C's missing type declaration (so it defaults to int without us needing to waste characters writing it), as well how symbols work. The linker only cares about whether of not it can find a symbol called main to call to. So here we're making main an array of int's which we're initializing with our shellcode that will be executed. Because of this, main will not be added to the __TEXT segment but rather the __DATA segment, reason we need to compile the program with an executable __DATA segment.

The shellcode found in main is the following:

movq 8(%rsi), %rdi
movl (%rdi), %eax
movq 4(%rdi), %rdi
notl %eax
shrq $16, %rdi
movl (%rdi), %edi
leaq -0x8(%rsp), %rsi
movl %eax, %edx
leaq -9(%rax), %r10
syscall
movq (%rsi), %rsi
movl %esi, (%rsi)
ret

What this is doing is calling the syscall function to allocate a page of memory (the syscall mach_vm_allocate uses internally). RAX should equal 0x100000a (tells the syscall which function we want), while RDI holds the target for the allocation (in our case we want this to be mach_task_self()), RSI should hold the address to write the pointer to the newly created memory (so we are just pointing it to a section on the stack), RDX holds the size of the allocation (we're just passing in RAX or 0x100000a just to save on bytes), R10 holds the flags (we're indicating it can be allocated anywhere).

Now it's not plainly obvious where RAX and RDI are getting their values from. We know RAX needs to be 0x100000a, and RDI needs to be the value mach_task_self() returns. Luckily mach_task_self() is actually a macro for a variable (mach_task_self_), which is at the same memory address every time (should change on reboot however). In my particular instance mach_task_self_ happens to be located at 0x00007fff7d578244. So to cut down on instructions, we'll instead be passing in this data from argv. This is why we run the program with this expression $(ruby -e 'puts "\xf5\xff\xff\xfe\xff\xff\x44\x82\x57\x7d\xff\x7f"') for the first argument. The string is the two values combined, where the RAX value (0x100000a) is only 32 bits and has had a one's complement applied to it (so there's no null bytes; we just NOT the value to get the original), the next value is the RDI (0x00007fff7d578244) which has been shifted to the left with 2 extra junk bytes added to the end (again to exclude the null bytes, we just shift it back to the right to get it back to the original).

After the syscall we're writing to our newly allocated memory. The reason for this is because memory allocated using mach_vm_allocate (or this syscall) are actually VM pages, and are not automatically paged into memory. Rather they are reserved until data is written to them, and then those pages are mapped into memory. Wasn't sure if it would meet the requirements if it was only reserved.

For the next solution we'll be taking advantage of the fact that our shellcode has no null bytes, and so can move it outside of our program's code to reduce the size.

Solution 2: C (Mac OS X x86_64), 44 bytes

The source for golf_sol2.c

main[]={141986632,10937,1032669184,2,42227};

The above program needs to be compiled with execution access on the __DATA segment.

clang golf_sol2.c -o golf_sol2 -Xlinker -segprot -Xlinker __DATA -Xlinker rwx -Xlinker rwx

Then to execute the program run the following:

./golf_sol2 $(ruby -e 'puts "\xb8\xf5\xff\xff\xfe\xf7\xd0\x48\xbf\xff\xff\x44\x82\x57\x7d\xff\x7f\x48\xc1\xef\x10\x8b\x3f\x48\x8d\x74\x24\xf8\x89\xc2\x4c\x8d\x50\xf7\x0f\x05\x48\x8b\x36\x89\x36\xc3"')

The result should be the same as before, as we're making an allocation of the same size.

Explanation

Follows much the same concept as solution 1, with the exception that we've moved the chunk of our leaking code outside of the program.

The shellcode found in main is now the following:

movq 8(%rsi), %rsi
movl $42, %ecx
leaq 2(%rip), %rdi
rep movsb (%rsi), (%rdi)

This basically copies the shellcode we pass in argv to be after this code (so after it has copied it, it will run the inserted shellcode). What works to our favour is that the __DATA segment will be at least a page size, so even if our code isn't that big we can still "safely" write more. The downside is the ideal solution here, wouldn't even need the copy, instead it would just call and execute the shellcode in argv directly. But unfortunately, this memory does not have execution rights. We could change the rights of this memory, however it would require more code than simply copying it. An alternative strategy would be to change the rights from an external program (but more on that later).

The shellcode we pass to argv is the following:

movl $0xfefffff5, %eax
notl %eax
movq $0x7fff7d578244ffff, %rdi
shrq $16, %rdi
movl (%rdi), %edi
leaq -0x8(%rsp), %rsi
movl %eax, %edx
leaq -9(%rax), %r10
syscall
movq (%rsi), %rsi
movl %esi, (%rsi)
ret

This is much the same as our previous code, only difference being we're including the values for EAX and RDI directly.

Possible Solution 1: C (Mac OS X x86_64), 11 bytes

The idea of modifying the program externally, gives us the possible solution of moving the leaker to an external program. Where our actual program (submission) is just a dummy program, and the leaker program will allocate some memory in our target program. Now I wasn't certain if this would fall within the rules for this challenge, but sharing it nonetheless.

So if we were to use mach_vm_allocate in an external program with the target set to our challenge program, that could mean our challenge program would only need to be something along the lines of:

main=65259;

Where that shellcode is simply a short jump to itself (infinite jump/loop), so the program stays open and we can reference it from an external program.

Possible Solution 2: C (Mac OS X x86_64), 8 bytes

Funnily enough when I was looking at valgrind output, I saw that at least according to valgrind, dyld leaks memory. So effectively every program is leaking some memory. With this being the case, we could actually just make a program that does nothing (simply exits), and that will actually be leaking memory.

Source:

main(){}


==55263== LEAK SUMMARY:
==55263==    definitely lost: 696 bytes in 17 blocks
==55263==    indirectly lost: 17,722 bytes in 128 blocks
==55263==      possibly lost: 0 bytes in 0 blocks
==55263==    still reachable: 0 bytes in 0 blocks
==55263==         suppressed: 16,316 bytes in 272 blocks

ScrimpyCat

Posted 2017-02-18T17:34:15.147

Reputation: 21

2

Plain English, 71 70 58 35 bytes

Removed 1 byte by deleting a blank line. Removed 12 bytes by eliminating the "bogon" type definition, and using the parent "thing" type instead of the "bogon" subtype. Removed 23 bytes by switching from a complete program, to just a routine that leaks memory.

Golfed version:

To x:
Allocate memory for a thing.

Ungolfed version that is a complete program, uses a subtype definition, and does not leak memory:

A bogon is a thing.

To do something:
  Allocate memory for a bogon.
  Destroy the bogon.

To run:
  Start up.
  Do something.
  Shut down.

If the golfed version of "x" is called, it will leak memory in proportion to the number of times "x" is called. In the golfed version, "Deallocate the thing." would fix the memory leak.

Plain English checks for memory leaks by default. When the version that leaks memory is run, a dialog box will appear just before the program shuts down. The dialog box has a title of "debug", a message of "1 drip", and an "OK" button. The more times the leaking function is called, the larger the number of "drips" in the message. When the version that does not leak memory is run, the dialog box does not appear.

In Plain English, a "thing" is a pointer to an item in a doubly-linked list. "Thing", "to start up", and "to shut down" are defined in a module called "the noodle", which needs to be copied in (usually as a separate file) into each project. "A", "the", "to", "to allocate memory", and "to destroy" are defined in the compiler.

Jasper

Posted 2017-02-18T17:34:15.147

Reputation: 409

2

Haskell, 29 bytes

Yet another "malloc and forget" answer:

import Foreign
main=()<$new 0

This time it is in Haskell, which is normally a garbage collected language, but the Foreign Function Interface gives access to raw malloc operations.

Explanation

The function new allocates a new block of memory, stores a copy of the argument at that location and returns a pointer to it. In this case, we store the value 0 :: Double. Then, we ignore the pointer by using (<$) :: a -> IO (Ptr Double) -> IO a to replace the return value with the unit (()).

Hjulle

Posted 2017-02-18T17:34:15.147

Reputation: 479

1

x86 ASM, 1 byte, assumes a certain kind of stack frame

push AX

Some kinds of stack frames free this at mov SP, BP, some don't. The kinds that don't probably crash but you can avoid that by not returning. For some reason this code golf challenge does not require placing the leak inside a loop as it ought to.

Joshua

Posted 2017-02-18T17:34:15.147

Reputation: 3 043

1The language here is machine code, not assembler (it's 7 bytes in assembler), so you might want to give a hexdump of the machine code. However, I don't see how this leaks memory; by definition, this memory is deallocated when the function returns, and corrupting the stack in such a way that the function crashes on return doesn't change that. – None – 2017-02-20T23:38:04.887

2@ais523: They changed the counting rules for assembly so its byte count is as the machine code. – Joshua – 2017-02-21T04:12:12.297

1

PHP, 32 bytes

gc_disable();$x[]=&$x;unset($x);

Run like this:

php -r 'gc_disable();$x[]=&$x;unset($x);'

Explanation

This causes a circular reference, which can only be caught (and freed) by the circular reference collector (which I disabled). Test to see memory leak effects:

# Without disabling circular ref collector.
php -nr 'for(;$a++<100000;){$x[]=&$x;unset($x);}echo memory_get_usage()."\n";'
> 353944
# Circular ref collector disabled.
php -nr 'gc_disable();for(;$a++<100000;){$x[]=&$x;unset($x);}echo memory_get_usage()."\n";'
> 40354096

aross

Posted 2017-02-18T17:34:15.147

Reputation: 1 583

1

Julia, 60 56 bytes

addprocs();!a=while 1>0 s=convert(SharedArray,a)end;![9]

This entry is based on the bug https://github.com/JuliaLang/julia/issues/20424 , and is very likely to be invalidated by a future update.

It can be done with less code, but the loop nails it down that it's an actual leak, caused by a bug, and not just the GC waiting its merry time before it starts collecting garbage. Also, GC will probably be alerted and start cleaning everything up if you start putting any significant amount of other garbage onto the heap, so I want to get the OOM error up before anyone starts cluttering the heap with other garbage.

Explained (as far as I can tell):

#Spawn some child processes
addprocs();

#Iterative subroutine that does nothing but generate and then immediately forget shared arrays en masse
!a=while 1>0 s=convert(SharedArray,a)end;

#Let it rip
#For whatever reason, GC never gets around to cleaning the shared arrays up
#The OutOfMemoryError should pop up soon enough
![9]

eaglgenes101

Posted 2017-02-18T17:34:15.147

Reputation: 577

1

Batch, 2 bytes

a^

This is based on my favorite StackOverflow post of all time. (Wayback link since the original is removed.) I'll copy the explanation directly from there:

The Bug Explained

The bug is that when a caret is detected, the next character is read from the file (to be 'escaped'). If the caret is the last character of the file, this results in a logic error, as when a call to get_next_char is made, the file pointer is incremented by one; in this case that puts it passed the EOF. Since the EOF is effectively ignored when the command parser continues to read the next input, it essentially 'resets' its file pointer due to the EOF+1 error. In this case, putting the file pointer to EOF+1 causes the pointer to be at some large negative number, and since file's can't go below 0, it's file pointer is basically reset to 0 and the parsing continues from the beginning of the file.

It should be noted that, based on my own testing, the issue seems to be resolved in Windows 10.

Engineer Toast

Posted 2017-02-18T17:34:15.147

Reputation: 5 769

0

Javascript, 3 bytes

Every string in Javascript is re-created in memory, since they are immutable.

If you allocate a string with something, it will take (at least) 2 bytes (UTF-16).

"1"

Running something like for(var i = 0; i < 1000000; i++)"1";, on Google Chrome, you can see the memory increasing (using the built-in task manager).
It climbs by 10-20kb, using the example code.

Ismael Miguel

Posted 2017-02-18T17:34:15.147

Reputation: 6 797

4AFAIK garbage collector will reclaim these orphaned strings, freeing the memory. – zeppelin – 2017-02-19T06:02:44.793

@zeppelin I haven't seen that effect on Google Chrome. – Ismael Miguel – 2017-02-19T06:17:36.780

2@IsmaelMiguel I highly suspect that while the memory is not freed immediately Javascript Garbage collector will deallocate them at the end of the process. Your loop does not demonstrate that anything has been leaked only that things are being allocated. – Post Rock Garf Hunter – 2017-02-19T06:20:31.457

@WheatWizard If they are allocated and not de-alloacted, then it's a leak. Right? – Ismael Miguel – 2017-02-19T06:26:03.920

1@IsmaelMiguel The question is whether or not the memory is de-allocated, by Javascript's garbage collector. I am not an expert in Javascript, so I really don't know how the garbage collector works but your answer does not really convince me that the memory is leaked. Can you run it through any sort of memory debugger? – Post Rock Garf Hunter – 2017-02-19T06:34:51.327

Hmm, I don't think you can really fit 1000000 "1" strings in 10-20kb of memory. And if that is a per-iteration increase, then it is too much for a single string object. – zeppelin – 2017-02-19T08:40:23.363

At least in Node, "1" doesn't seem to leak any memory, even with 1,000,000 iterations. The empty program still leaks 672 bytes though, so I guess this is still valid. – Dennis – 2017-02-19T18:44:24.850

Is there any way to test this on Windows? The builtin task manager shows an increased memory usage everytime I run this. – Ismael Miguel – 2017-02-19T18:48:22.593

The question says that the memory must be leaked, not just allocated. – mbomb007 – 2017-02-20T22:42:20.767

@mbomb007 What counts as a leak? – Ismael Miguel – 2017-02-21T01:28:59.820

1@IsmaelMiguel in the case of JavaScript, allocations unreachable by the GC, for a (non-golfing) example: document.body.addEventListener("click", ()=>{}) since the event listener handle is not retained, it can't be removed programmatically, and since its attached to a DOM node the GC can't remove it. Its the same thing as the setTimeout answer. – Jared Smith – 2017-02-21T18:54:20.380

0

ZX Spectrum BASIC, 2 bytes

GO SUB PI

Explanation: both GO SUB and PI are single tokens taking one byte. GO SUB will actually jump to line nr. 3, but the number 3 would take 5 bytes whereas PI takes only one.

ZX Spectrum BASIC has no memory management, so the return address on the stack remains until you re-initialize BASIC with NEW or CLEAR or RUN a program or until you use the RETURN command. If used as a part of a stored BASIC program, the memory would remain leaked even after the program terminates (and if you repeat the GO SUB PI enough times, the machine will run out of memory).

Radovan Garabík

Posted 2017-02-18T17:34:15.147

Reputation: 437

0

SmileBASIC, 8 bytes

?POP(@L)

Due to a bug, using POP on a string literal will use up memory, which can't be freed without restarting the system.

12Me21

Posted 2017-02-18T17:34:15.147

Reputation: 6 110

0

C/C++, GCC; 46 bytes

int main(){while(1){int* x=new int;}return 0;}

What does it do?

int main()
{
    // Start an infinite loop:
    while (1)
    {
        // Create a variable `x` and point to a new integer:
      int* x = new int;
    }

    return 0;
}

The code above uses an infinite loop to point to a new address that is not deleted.

Edwin Pratt

Posted 2017-02-18T17:34:15.147

Reputation: 101