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.
-
2\$\begingroup\$ Perhaps you could have different ranges of amount leaked and depending on how much you leak you lose x% of your byte count \$\endgroup\$user63187– user631872017年02月18日 17:38:07 +00:00Commented Feb 18, 2017 at 17:38
-
11\$\begingroup\$ @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. \$\endgroup\$Wheat Wizard– Wheat Wizard ♦2017年02月18日 18:01:51 +00:00Commented Feb 18, 2017 at 18:01
-
1\$\begingroup\$ Related. Not a duplicate, though, because most answers to that question form an infinite reachable structure in memory rather than actually leaking memory. \$\endgroup\$user62131– user621312017年02月18日 18:18:10 +00:00Commented Feb 18, 2017 at 18:18
-
2\$\begingroup\$ what is the idea? That the mem cannot be freed? I guess this would require native execution for garbage collected languages or exploiting bugs. \$\endgroup\$akostadinov– akostadinov2017年02月18日 21:26:49 +00:00Commented Feb 18, 2017 at 21:26
-
7\$\begingroup\$ I see how languages designed for golfing fail miserably on this one ... \$\endgroup\$Kh40tiK– Kh40tiK2017年02月19日 12:25:08 +00:00Commented Feb 19, 2017 at 12:25
42 Answers 42
Perl (5.22.2), 0 bytes
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)
-
17\$\begingroup\$ I 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 --versionon my machine, despite it never gets to running any program, at all. \$\endgroup\$zeppelin– zeppelin2017年02月19日 07:14:00 +00:00Commented Feb 19, 2017 at 7:14 -
12\$\begingroup\$ @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. \$\endgroup\$user62131– user621312017年02月19日 09:03:54 +00:00Commented Feb 19, 2017 at 9:03
-
9\$\begingroup\$ This also works in Node JS. \$\endgroup\$Dennis– Dennis2017年02月19日 18:40:16 +00:00Commented Feb 19, 2017 at 18:40
-
7\$\begingroup\$ This feels like a new standard loophole in the making... \$\endgroup\$Michael Hampton– Michael Hampton2017年02月22日 03:32:40 +00:00Commented Feb 22, 2017 at 3:32
-
57\$\begingroup\$ Finally a Perl script that I can understand. \$\endgroup\$user11153– user111532017年02月22日 16:05:18 +00:00Commented Feb 22, 2017 at 16:05
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
-
1\$\begingroup\$ @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... \$\endgroup\$tbodt– tbodt2017年02月18日 22:07:11 +00:00Commented Feb 18, 2017 at 22:07
-
1\$\begingroup\$ @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. \$\endgroup\$Riley– Riley2017年02月18日 22:27:07 +00:00Commented Feb 18, 2017 at 22:27
-
38\$\begingroup\$ Thank you for posting this. I just protected TIO against shared memory leaks. \$\endgroup\$Dennis– Dennis2017年02月18日 23:30:06 +00:00Commented Feb 18, 2017 at 23:30
-
4\$\begingroup\$ @Dennis That's why I didn't post a TIO link. I didn't know if it was protected or not. \$\endgroup\$Riley– Riley2017年02月18日 23:31:54 +00:00Commented Feb 18, 2017 at 23:31
-
15\$\begingroup\$ I like how you use the word problem to describe the scenario where the program leaks less memory than intended. \$\endgroup\$kasperd– kasperd2017年02月19日 14:24:22 +00:00Commented Feb 19, 2017 at 14:24
Unlambda (c-refcnt/unlambda), 1 byte
i
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)
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)
-
2\$\begingroup\$ Yep, most of us know the feeling ;) @RayKoopa \$\endgroup\$Timtech– Timtech2017年02月19日 02:44:31 +00:00Commented Feb 19, 2017 at 2:44
-
13\$\begingroup\$ +1 for Ti Basic. I spent most of my 9th grade year programming those things. \$\endgroup\$markasoftware– markasoftware2017年02月19日 03:26:14 +00:00Commented Feb 19, 2017 at 3:26
-
\$\begingroup\$ Do you need
Pauseat the end? You could save 2 bytes. \$\endgroup\$kamoroso94– kamoroso942017年02月19日 05:23:37 +00:00Commented Feb 19, 2017 at 5:23 -
\$\begingroup\$ @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. \$\endgroup\$Timtech– Timtech2017年02月19日 15:24:23 +00:00Commented Feb 19, 2017 at 15:24
-
\$\begingroup\$ A simpler "leak" under these rules would be to create a program named
prgmAconsisting of the single commandprgmA(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 theWhile"leak" can be reclaimed by hitting anEnd, 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. :) \$\endgroup\$Quuxplusone– Quuxplusone2017年02月20日 08:45:27 +00:00Commented Feb 20, 2017 at 8:45
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.)
-
\$\begingroup\$ Has a bug report been sent? \$\endgroup\$mbomb007– mbomb0072018年08月03日 14:39:14 +00:00Commented Aug 3, 2018 at 14:39
-
1\$\begingroup\$ @mbomb007: CPython issue 31787. \$\endgroup\$user2357112– user23571122018年08月03日 16:43:03 +00:00Commented Aug 3, 2018 at 16:43
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.
-
\$\begingroup\$ 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... \$\endgroup\$don bright– don bright2017年02月20日 00:50:13 +00:00Commented Feb 20, 2017 at 0:50
-
1\$\begingroup\$ A 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. \$\endgroup\$MrPaulch– MrPaulch2017年02月20日 07:01:50 +00:00Commented Feb 20, 2017 at 7:01
-
\$\begingroup\$ Wouldn't the challenge be complete by just using
class L{~L(){new L();}}? AFAIK thefor(;;)only makes it leak memory faster, right? \$\endgroup\$BgrWorker– BgrWorker2017年02月20日 08:05:51 +00:00Commented Feb 20, 2017 at 8:05 -
1\$\begingroup\$ Sadly, 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. \$\endgroup\$MrPaulch– MrPaulch2017年02月20日 08:09:57 +00:00Commented Feb 20, 2017 at 8:09
-
2\$\begingroup\$ Not really. Eventually one finalized will be ignored. The corresponding object will be eaten regardless. \$\endgroup\$MrPaulch– MrPaulch2017年02月20日 08:24:16 +00:00Commented Feb 20, 2017 at 8:24
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).
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.
-
6\$\begingroup\$ Haha I love that you've typed 'Golfed', makes me curious about the ungolfed version \$\endgroup\$Martijn– Martijn2017年02月20日 15:18:14 +00:00Commented Feb 20, 2017 at 15:18
-
9\$\begingroup\$ it might look like this
if(window && window.setInterval && typeof window.setInterval === 'function') { window.setInterval(0); }\$\endgroup\$Tschallacka– Tschallacka2017年02月20日 15:51:08 +00:00Commented Feb 20, 2017 at 15:51 -
4\$\begingroup\$ Actually, 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
clearIntervalwith an incrementing ID until your interval is gone. For example:for(let i=0;i<1e5;i++){try{clearInterval(i);}catch(ex){}}\$\endgroup\$user2428118– user24281182017年02月20日 22:40:02 +00:00Commented Feb 20, 2017 at 22:40 -
5\$\begingroup\$ @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()\$\endgroup\$TripeHound– TripeHound2017年02月21日 12:03:36 +00:00Commented Feb 21, 2017 at 12:03 -
1\$\begingroup\$ Wow, not many challenges where JavaScript is an actual contender... \$\endgroup\$Jared Smith– Jared Smith2017年02月21日 18:49:54 +00:00Commented Feb 21, 2017 at 18:49
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)
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)
-
\$\begingroup\$ 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. \$\endgroup\$don bright– don bright2019年03月04日 01:54:48 +00:00Commented Mar 4, 2019 at 1:54
-
\$\begingroup\$ I am not aware of any operating systems that have a
usizedefined asu8. It should befn malloc(_:usize);. \$\endgroup\$Sapphire_Brick– Sapphire_Brick2020年06月11日 01:45:35 +00:00Commented Jun 11, 2020 at 1:45 -
\$\begingroup\$ @Sapphire_Brick using the correct function prototype would waste 3 bytes. thus the comment "This assumes the wrong ABI is acceptable". \$\endgroup\$kennytm– kennytm2020年06月12日 15:55:40 +00:00Commented Jun 12, 2020 at 15:55
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 JavaTM 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.
-
2\$\begingroup\$ I 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). \$\endgroup\$VisualMelon– VisualMelon2017年02月19日 09:02:50 +00:00Commented Feb 19, 2017 at 9:02 -
1\$\begingroup\$ Indeed, 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 \$\endgroup\$VisualMelon– VisualMelon2017年02月19日 18:32:46 +00:00Commented Feb 19, 2017 at 18:32
-
3\$\begingroup\$ That 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. \$\endgroup\$user2357112– user23571122017年02月20日 01:00:19 +00:00Commented Feb 20, 2017 at 1:00
-
3\$\begingroup\$ @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? \$\endgroup\$zeppelin– zeppelin2017年02月20日 09:40:07 +00:00Commented Feb 20, 2017 at 9:40
-
2\$\begingroup\$ @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 toocould you demonstrate this ? (hint, String.intern() is implemented in the native code). \$\endgroup\$zeppelin– zeppelin2017年02月20日 15:44:17 +00:00Commented Feb 20, 2017 at 15:44
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!
-
\$\begingroup\$ The normal implementation of malloc will result in memory being freed on process exit. \$\endgroup\$Joshua– Joshua2017年11月17日 00:00:05 +00:00Commented Nov 17, 2017 at 0:00
-
\$\begingroup\$ @Joshua Yeah, but that's implementation defined behaviour. \$\endgroup\$FUZxxl– FUZxxl2017年11月17日 00:03:14 +00:00Commented Nov 17, 2017 at 0:03
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
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.
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'
-
1\$\begingroup\$ golf check: this is 2 bytes shorter than calling
C.malloc(8), since you need toimport"C"\$\endgroup\$VerdantOzark– VerdantOzark2017年03月01日 00:44:26 +00:00Commented Mar 1, 2017 at 0:44 -
1\$\begingroup\$ There are three kinds of answers. The low-level languages where you just
mallocthen discard it, the garbage collected languages where you create an infinite loop that doesn't give the garbage collector time to deallocate memory, and the garbage collected languages that leak memory due to a bug in the interpreter. \$\endgroup\$Sapphire_Brick– Sapphire_Brick2020年06月11日 01:49:25 +00:00Commented Jun 11, 2020 at 1:49
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());
}
}
}
-
\$\begingroup\$ Since this works only on specific Java versions, you should say "Java 3" in your header instead. \$\endgroup\$user18932– user189322017年02月20日 15:43:50 +00:00Commented Feb 20, 2017 at 15:43
-
5\$\begingroup\$ There'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. \$\endgroup\$Olivier Grégoire– Olivier Grégoire2017年02月21日 01:54:47 +00:00Commented Feb 21, 2017 at 1:54
-
\$\begingroup\$ This was my idea too. Damn. \$\endgroup\$Magic Octopus Urn– Magic Octopus Urn2017年06月28日 19:12:24 +00:00Commented Jun 28, 2017 at 19:12
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.
-
\$\begingroup\$ Hmm, you still can reference that memory through
xandy, so this does not really look like a leak to me (unless you destroy them somehow). \$\endgroup\$zeppelin– zeppelin2017年02月19日 06:19:03 +00:00Commented Feb 19, 2017 at 6:19 -
\$\begingroup\$ @zeppelin The last line could be wrapped in a function to fix that \$\endgroup\$NobodyNada– NobodyNada2017年02月19日 18:51:19 +00:00Commented Feb 19, 2017 at 18:51
-
\$\begingroup\$ @NobodyNada, if I were to put the last line in a
doblock that would fix the problem zeppelin raised right? \$\endgroup\$Daniel– Daniel2017年02月19日 19:04:07 +00:00Commented Feb 19, 2017 at 19:04 -
\$\begingroup\$ @Dopapp Yeah; a
dowould work as well. Good idea! \$\endgroup\$NobodyNada– NobodyNada2017年02月19日 19:17:12 +00:00Commented Feb 19, 2017 at 19:17 -
\$\begingroup\$ 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}\$\endgroup\$Sebastian Osiński– Sebastian Osiński2017年02月20日 18:59:11 +00:00Commented Feb 20, 2017 at 18:59
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:
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.
-
2\$\begingroup\$
System.IO.File.Create("a")won't leak anything, butGC.SuppressFinalize(System.IO.File.Create("a"))will as it is explicitly asked not to run the finaliser of theFileStreamproduced. \$\endgroup\$Jon Hanna– Jon Hanna2017年02月19日 03:13:31 +00:00Commented Feb 19, 2017 at 3:13 -
\$\begingroup\$ @JonHanna quite right. My IDisposable paranoia seems to have got the better of me. \$\endgroup\$VisualMelon– VisualMelon2017年02月19日 08:40:41 +00:00Commented Feb 19, 2017 at 8:40
-
\$\begingroup\$ 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. \$\endgroup\$BgrWorker– BgrWorker2017年02月20日 07:42:35 +00:00Commented Feb 20, 2017 at 7:42
-
\$\begingroup\$ @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! \$\endgroup\$VisualMelon– VisualMelon2017年02月20日 17:45:58 +00:00Commented Feb 20, 2017 at 17:45
-
\$\begingroup\$
<!-- language: lang-c# -->Thanks for this & nice answer! (It's C# so I love it) \$\endgroup\$Mika– Mika2017年02月22日 13:50:41 +00:00Commented Feb 22, 2017 at 13:50
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:
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.
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.
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 bothmake-alienandintwithsb-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.make-alienallocates memory for a given type and an optional size (using malloc).When executing this in the REPL, add
0after 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!
-
1\$\begingroup\$ Can't you use
1(or2,3, etc.) instead of()so that you return value1? It would save 1 byte. Also is this answer REPL only? Maybe if you load code withloadyou can not include()or anything at the end, because it will not be accessible anyway? \$\endgroup\$user65167– user651672017年11月29日 23:20:28 +00:00Commented Nov 29, 2017 at 23:20 -
1\$\begingroup\$ @PrzemysławP You are right on both points, I tried with
evaland this works as you said. Thanks a lot! \$\endgroup\$coredump– coredump2017年11月30日 08:42:39 +00:00Commented Nov 30, 2017 at 8:42
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
-
\$\begingroup\$ @WheatWizard I am using
g++ 4.3.2(not the most recent one) and it compiles just fine. No return type isintby default I think. With-WallI have a warning though:plop.cpp:1: warning: ISO C++ forbids declaration of 'main' with no type\$\endgroup\$matovitch– matovitch2017年02月20日 15:54:53 +00:00Commented Feb 20, 2017 at 15:54 -
2\$\begingroup\$ @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. :/ \$\endgroup\$matovitch– matovitch2017年02月20日 16:19:10 +00:00Commented Feb 20, 2017 at 16:19
-
\$\begingroup\$ Consensus is that you can count just
[]{new int;}as a C++ function (the challenge didn't specify a whole program). \$\endgroup\$Toby Speight– Toby Speight2018年08月03日 11:39:13 +00:00Commented Aug 3, 2018 at 11:39
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 0ドルxfefffff5, %eax
notl %eax
movq 0ドルx7fff7d578244ffff, %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
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);}}
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
-
\$\begingroup\$ You can save a bunch of bytes by obtaining the
Unsafeinstance 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);}}\$\endgroup\$zeppelin– zeppelin2017年02月20日 10:23:26 +00:00Commented Feb 20, 2017 at 10:23 -
\$\begingroup\$ And you can save some more by replacing the
public static void mainby a static initializerstatic{try{}catch(Exception e){}}(which could be a bit more tricky to launch but is nevertheless valid and compilable). \$\endgroup\$zeppelin– zeppelin2017年02月20日 10:25:58 +00:00Commented Feb 20, 2017 at 10:25 -
\$\begingroup\$ 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 ;) \$\endgroup\$Serverfrog– Serverfrog2017年02月20日 17:42:01 +00:00Commented Feb 20, 2017 at 17:42
-
\$\begingroup\$ Remove whitespace, use
ainstead ofargs, and remove public. tio.run/nexus/… \$\endgroup\$Pavel– Pavel2017年02月21日 08:02:12 +00:00Commented Feb 21, 2017 at 8:02 -
\$\begingroup\$ true can be replaced with 1>0 \$\endgroup\$masterX244– masterX2442017年02月23日 14:51:03 +00:00Commented Feb 23, 2017 at 14:51
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 inpage_loadof one of my pagesXmlSerializer serializer = new XmlSerializer(typeof(PurchaseOrder), new XmlRootAttribute(""));This would seem like a pretty innocent piece of code. We create an
XMLSerializerforPurchaseOrder. But what happens under the covers?If we take a look at the
XmlSerializerconstructor with Reflector we find that it callsthis.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.
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
-
2\$\begingroup\$ Is it possible to instead just do
main(){malloc(1);}? \$\endgroup\$kirbyfan64sos– kirbyfan64sos2017年02月20日 18:46:24 +00:00Commented Feb 20, 2017 at 18:46 -
\$\begingroup\$ @Yea it is! But its already been posted! \$\endgroup\$Abel Tom– Abel Tom2017年02月20日 18:52:06 +00:00Commented Feb 20, 2017 at 18:52
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.
-
\$\begingroup\$ 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. \$\endgroup\$don bright– don bright2017年02月21日 05:06:20 +00:00Commented Feb 21, 2017 at 5:06
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])
-
\$\begingroup\$ Whaaaaaaaaaaat? \$\endgroup\$Sapphire_Brick– Sapphire_Brick2020年07月01日 18:44:40 +00:00Commented Jul 1, 2020 at 18:44
-
\$\begingroup\$ @Sapphire_Brick Hmm? \$\endgroup\$Alexander– Alexander2020年07月01日 23:54:10 +00:00Commented Jul 1, 2020 at 23:54
-
\$\begingroup\$ @AlexanderReinstateMonica I'm just shocked that such a simple code causes a memory leak. \$\endgroup\$Sapphire_Brick– Sapphire_Brick2020年07月02日 19:39:38 +00:00Commented Jul 2, 2020 at 19:39
-
\$\begingroup\$ @Sapphire_Brick Yep, I haven't seen any automated memory management systems that can clear up something like this. The book keeping required to know that you're only using a small portion of a large allocated object is probably not worth the performance cost it introduces \$\endgroup\$Alexander– Alexander2020年07月02日 19:50:41 +00:00Commented Jul 2, 2020 at 19:50
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)
-
3\$\begingroup\$ You're not actually leaking memory;
gccis. This should also work with the empty program. Trygcc src.c && valgrind ./a.out, which should produce a clean result. \$\endgroup\$user77406– user774062018年10月29日 20:20:11 +00:00Commented Oct 29, 2018 at 20:20 -
\$\begingroup\$ @user77406 The perl answer which is 0 bytes and the unlambda answer which is 1 byte also have this property. Like all things in code golf, if it isn't prohibited in the standard loopholes, anything is game if you get the right answer. \$\endgroup\$Jerry Jeremiah– Jerry Jeremiah2020年06月09日 21:56:02 +00:00Commented Jun 9, 2020 at 21:56
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.