หน่วยความจำรั่วในไบต์น้อยที่สุด


79

งานของคุณคือการเขียนโค้ดที่จะรั่วอย่างน้อยหนึ่งไบต์ของหน่วยความจำในไม่กี่ไบต์เท่าที่จะทำได้ หน่วยความจำที่จะต้องมีการรั่วไหลออกมาไม่ได้เป็นเพียงการจัดสรร

หน่วยความจำรั่วคือหน่วยความจำที่โปรแกรมจัดสรร แต่สูญเสียความสามารถในการเข้าถึงก่อนที่จะสามารถจัดสรรคืนหน่วยความจำได้อย่างถูกต้อง สำหรับภาษาระดับสูงส่วนใหญ่หน่วยความจำนี้จะต้องมีการจัดสรรในกอง

ตัวอย่างใน C ++ จะเป็นโปรแกรมต่อไปนี้:

int main(){new int;}

สิ่งนี้ทำให้new intบนฮีปโดยไม่มีตัวชี้ไป หน่วยความจำนี้รั่วไหลออกมาทันทีเพราะเราไม่สามารถเข้าถึงได้

นี่คือสิ่งที่สรุปการรั่วไหลจากValgrindอาจมีลักษณะ:

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

หลายภาษามีตัวดีบักหน่วยความจำ (เช่นValgrind ) ถ้าคุณสามารถคุณควรรวมเอาเอาท์พุทจากตัวดีบักเพื่อยืนยันว่าคุณมีหน่วยความจำรั่วไหล

เป้าหมายคือเพื่อลดจำนวนไบต์ในแหล่งที่มาของคุณ


2
บางทีคุณอาจมีช่วงที่แตกต่างกันของจำนวนเงินที่รั่วไหลออกไปและขึ้นอยู่กับว่าคุณรั่วไหลมากแค่ไหนคุณเสีย x% ของจำนวนไบต์
Christopher

11
@ChristopherPeart สำหรับฉันไม่ใช่แฟนของโบนัสสำหรับความท้าทายและสำหรับสองอย่างที่คุณแสดงให้เห็นแล้วมันง่ายมากที่จะรั่วไหลความทรงจำที่ไม่ได้ จำกัด
ข้าวสาลีตัวช่วยสร้าง

1
ที่เกี่ยวข้อง ไม่ใช่คำตอบที่ซ้ำกันเนื่องจากคำตอบส่วนใหญ่สร้างโครงสร้างที่สามารถเข้าถึงได้ไม่ จำกัด ในหน่วยความจำแทนที่จะรั่วหน่วยความจำจริง

2
ความคิดคืออะไร? ว่า mem ไม่สามารถเป็นอิสระได้? ฉันเดาว่าสิ่งนี้จะต้องมีการเรียกใช้ภาษาพื้นเมืองสำหรับภาษาที่รวบรวมขยะหรือใช้ประโยชน์จากข้อบกพร่อง
akostadinov

7
ผมเห็นว่าภาษาที่ออกแบบมาสำหรับการเล่นกอล์ฟล้มไม่เป็นท่าในนี้ ...
Kh40tiK

คำตอบ:


89

Perl (5.22.2), 0 ไบต์

ลองออนไลน์!

ฉันรู้ว่ามีบางภาษาที่มีหน่วยความจำรั่วไหลในโปรแกรมที่ว่างเปล่า ฉันคาดหวังว่ามันจะเป็น esolang แต่กลับกลายเป็นว่าperlหน่วยความจำรั่วในโปรแกรมใด ๆ (ฉันสมมติว่านี่เป็นความตั้งใจเพราะการเพิ่มหน่วยความจำถ้าคุณรู้ว่าคุณกำลังจะออกไปแล้วก็เสียเวลาดังนั้นคำแนะนำทั่วไปในทุกวันนี้ก็คือการรั่วไหลของหน่วยความจำที่เหลืออยู่เมื่อคุณอยู่ในรูทีนทางออกของโปรแกรม .)

การตรวจสอบ

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

16
ฉันชอบคำตอบ Unlambda แต่อันนี้ (IMHO) ยืดเกินไปเพราะเห็นได้ชัดว่าล่ามตัวเองซึ่งหน่วยความจำรั่วนั่นคือฉันได้รับ 'สูญหายแน่นอน: 7,742 bytes ใน 14 block` เมื่อฉันทำงานperl --versionบนเครื่องของฉัน แม้จะไม่เคยใช้งานโปรแกรมใด ๆ เลย
เรือเหาะที่

11
@zeppelin: เห็นด้วย แต่ตามกฎของเรามันเป็นการนำไปปฏิบัติที่กำหนดภาษาดังนั้นหากการดำเนินการรั่วไหลของหน่วยความจำทุกโปรแกรมในหน่วยความจำภาษารั่วไหล ฉันไม่แน่ใจว่าฉันเห็นด้วยกับกฎนี้ แต่ ณ จุดนี้มันยึดมั่นเกินไปที่จะสามารถเปลี่ยนแปลงได้

8
สิ่งนี้ยังทำงานในโหนด JS
เดนนิส

6
นี่ให้ความรู้สึกเหมือนเป็นช่องโหว่มาตรฐานใหม่ในการสร้าง ...
Michael Hampton

46
ในที่สุดสคริปต์ Perl ที่ฉันสามารถเข้าใจ
user11153

66

C, 48 31 22 ไบต์

คำเตือน: อย่าเรียกใช้งานหลายครั้งเกินไป

ขอบคุณเดนนิสสำหรับความช่วยเหลือ / แนวคิดมากมาย!

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

สิ่งนี้จะไปอีกขั้นหนึ่ง shmgetจัดสรรหน่วยความจำแบบแบ่งใช้ที่ไม่ได้ถูกจัดสรรคืนเมื่อโปรแกรมสิ้นสุด มันใช้คีย์เพื่อระบุหน่วยความจำดังนั้นเราจึงใช้ int ไม่กำหนดค่าเริ่มต้น นี่เป็นพฤติกรรมที่ไม่ได้กำหนดทางเทคนิค แต่จริงๆแล้วมันหมายความว่าเราใช้ค่าที่อยู่เหนือส่วนบนสุดของสแต็กเมื่อเรียกสิ่งนี้ สิ่งนี้จะถูกเขียนในครั้งต่อไปที่มีการเพิ่มสิ่งใดลงในสแต็กดังนั้นเราจะสูญเสียรหัส


กรณีเดียวที่สิ่งนี้ไม่ได้ผลคือถ้าคุณสามารถคิดได้ว่ามีอะไรอยู่ในสแต็กมาก่อน สำหรับอีก 19 ไบต์คุณสามารถหลีกเลี่ยงปัญหานี้ได้:

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

หรือสำหรับ 26 ไบต์:

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

แต่ด้วยหน่วยความจำนี้หน่วยความจำจะรั่วไหลหลังจากออกจากโปรแกรม ในขณะที่เรียกใช้โปรแกรมมีการเข้าถึงหน่วยความจำที่ผิดกฎ แต่หลังจากที่โปรแกรมยุติเราจะสูญเสียการเข้าถึงกุญแจและหน่วยความจำยังคงถูกจัดสรร สิ่งนี้ต้องใช้การสุ่มเลย์เอาต์พื้นที่ที่อยู่ (ASLR) มิฉะนั้น&kจะเหมือนกันเสมอ ทุกวันนี้ ASLR เปิดอยู่ตามปกติ


ยืนยัน:

คุณสามารถใช้ipcs -mเพื่อดูว่าหน่วยความจำที่ใช้ร่วมกันมีอยู่ในระบบของคุณ ฉันลบรายการที่มีอยู่ล่วงหน้าเพื่อความชัดเจน:

$ 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
@AndrewSavinykh ในทางทฤษฎี shmid อาจถูกเก็บไว้ในไฟล์และโปรแกรมสามารถแนบไปกับมันในอนาคต นี่คือวิธีที่หน่วยความจำที่ใช้ร่วมกันของยูนิกซ์ทำงานได้ ...
2017

1
@AndrewSavinykh หน่วยความจำที่ใช้ร่วมกันโดยทั่วไปจะกลายเป็นทรัพยากรที่ระบบปฏิบัติการสามารถมอบให้กับกระบวนการอื่น ๆ มันคล้ายกับไฟล์ที่อยู่ใน RAM และกระบวนการใด ๆ ที่รู้ชื่อ (คีย์) สามารถเข้าถึงได้จนกว่าจะถูกลบ ลองนึกภาพกระบวนการที่คำนวณตัวเลขและเก็บไว้ในหน่วยความจำและออกก่อนที่กระบวนการที่จะอ่านข้อมูลที่เชื่อมต่อกับหน่วยความจำที่ใช้ร่วมกัน ในกรณีนี้ถ้าระบบปฏิบัติการปลดปล่อยหน่วยความจำกระบวนการที่สองจะไม่สามารถทำได้
Riley

35
ขอขอบคุณสำหรับการโพสต์นี้. ฉันเพิ่งป้องกัน TIO จากการรั่วไหลของหน่วยความจำที่ใช้ร่วมกัน
Dennis

4
@Dennis นั่นเป็นสาเหตุที่ฉันไม่ได้โพสต์ลิงค์ TIO ฉันไม่รู้ว่ามันได้รับการคุ้มครองหรือไม่
ไรลีย์

12
ฉันชอบวิธีที่คุณใช้ปัญหาคำเพื่ออธิบายสถานการณ์ที่โปรแกรมรั่วหน่วยความจำน้อยกว่าที่ตั้งใจไว้
kasperd

40

Unlambda ( c-refcnt/unlambda), 1 ไบต์

i

ลองออนไลน์!

นี่เป็นความท้าทายอย่างมากเกี่ยวกับการหาล่ามที่มีอยู่แล้วซึ่งทำให้หน่วยความจำรั่วไหลในโปรแกรมที่ง่าย ในกรณีนี้ฉันใช้ Unlambda มีล่ามอย่างเป็นทางการของ Unlambda มากกว่าหนึ่งตัว แต่c-refcntเป็นหนึ่งในวิธีที่ง่ายที่สุดในการสร้างและมีคุณสมบัติที่เป็นประโยชน์ที่นี่ซึ่งทำให้หน่วยความจำรั่วเมื่อโปรแกรมทำงานได้สำเร็จ ดังนั้นสิ่งที่ฉันต้องให้ที่นี่คือโปรแกรม Unlambda ทางกฎหมายที่ง่ายที่สุดที่เป็นไปได้ (โปรดทราบว่าโปรแกรมเปล่าไม่ทำงานที่นี่หน่วยความจำยังสามารถเข้าถึงได้ในขณะที่ล่ามเกิดปัญหา)

การตรวจสอบ

$ wget ftp://ftp.madore.org/pub/madore/unlambda/unlambda-2.0.0.tar.gz
... บุคคลที่ไม่สำคัญ ...
2017-02-18 18:11:08 (975 KB / s) - บันทึก 'unlambda-2.0.0.tar.gz' แล้ว [492894]
$ tar xf unlambda-2.0.0.tar.gz 
$ cd unlambda-2.0.0 / c-refcnt /
$ gcc unlambda.c
$ echo -ni | valgrind ./a.out / dev / stdin
... บุคคลที่ไม่สำคัญ ...
== 3417 == สรุปการรั่วไหล:
== 3417 == หายไปอย่างแน่นอน: 40 ไบต์ใน 1 บล็อก
== 3417 == สูญเสียทางอ้อม: 0 ไบต์ใน 0 บล็อก
== 3417 == อาจหายไป: 0 ไบต์ใน 0 บล็อก
== 3417 == ยังเข้าถึงได้: 0 ไบต์ใน 0 บล็อก
== 3417 == ถูกระงับ: 0 ไบต์ใน 0 บล็อก
== 3417 == 
== 3417 == สำหรับจำนวนข้อผิดพลาดที่ตรวจพบและระงับให้รันด้วย: -v
== 3417 == สรุปข้อผิดพลาด: 1 ข้อผิดพลาดจาก 1 บริบท (ถูกระงับ: 0 จาก 0)

39

TI-Basic, 12 ไบต์

While 1
Goto A
End
Lbl A
Pause 

"... การรั่วไหลของหน่วยความจำคือที่ที่คุณใช้ Goto / Lbl ภายในลูปหรือหากเงื่อนไข (สิ่งใดก็ตามที่มีคำสั่ง End) เพื่อกระโดดออกจากโครงสร้างการควบคุมนั้นก่อนที่คำสั่ง End จะมาถึง ... " (เพิ่มเติม)


7
ว้าวฉันคิดว่าฉันจำสิ่งนี้ได้ ฉันยังคงกระโดดออกจากลูปของฉันในโปรแกรมพื้นฐานเก่าของฉันและสังเกตเห็นว่า TI-84 + ของฉันช้าลงและช้าลงอย่างไร ...
Ray

2
ใช่พวกเราส่วนใหญ่รู้ถึงความรู้สึก;) @RayKoopa
Timtech

13
+1 สำหรับ Ti Basic ฉันใช้เวลาส่วนใหญ่ในการเขียนโปรแกรมชั้นปีที่ 9 ของฉัน
markasoftware

คุณต้องการPause ที่สิ้นสุดหรือไม่ คุณสามารถบันทึก 2 ไบต์
kamoroso94

@ kamoroso94 ฉันคิดอย่างนั้นเพราะ "หากโปรแกรมสิ้นสุดลงการรั่วไหลจะถูกล้างออกและจะทำให้ไม่มีปัญหาเพิ่มเติม" ดังนั้นจึงเป็นการหยุดโปรแกรมจากการสิ้นสุด
Timtech

32

Python <3.6.5, 23 ไบต์

property([]).__init__()

property.__init__การรั่วไหลของการอ้างอิงไปยังสถานที่ให้บริการเก่าfget, fset, fdelและ__doc__ถ้าคุณเรียกมันบนแล้วเริ่มต้นpropertyอินสแตนซ์ ปัญหานี้เป็นปัญหาในที่สุดก็รายงานว่าเป็นส่วนหนึ่งของ CPython ปัญหา 31787และการแก้ไขในPython 3.6.5และPython 3.7.0 (นอกจากนี้ใช่property([])เป็นสิ่งที่คุณสามารถทำได้)


ส่งรายงานข้อบกพร่องแล้วหรือยัง
mbomb007


27

C #, 34 ไบต์

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

นี้การแก้ปัญหาไม่จำเป็นต้องมีกอง มันแค่ต้องการ GC จริง ๆ ที่ทำงานหนัก ( Garbage Collector )

โดยพื้นฐานแล้วมันจะเปลี่ยน GC เป็นศัตรูของมันเอง

คำอธิบาย

เมื่อใดก็ตามที่มีการเรียกตัวทำลายมันจะสร้างอินสแตนซ์ใหม่ของคลาสที่ชั่วร้ายนี้ตราบใดที่หมดเวลาและหมดเวลาและบอกให้ GC ทำการทิ้งวัตถุนั้นโดยไม่ต้องรอให้ตัวทำลายเสร็จสิ้น เมื่อมีอินสแตนซ์ใหม่หลายพันรายการถูกสร้างขึ้น

"ความชั่วร้าย" ของสิ่งนี้คือยิ่ง GC ทำงานหนักมากเท่าไหร่ก็ยิ่งทำให้หน้าของคุณระเบิดได้มากขึ้นเท่านั้น

คำเตือน : GC ของคุณอาจฉลาดกว่าของฉัน สถานการณ์อื่น ๆ ในโปรแกรมอาจทำให้ GC ละเว้นวัตถุแรกหรือตัวทำลายได้ ในกรณีนี้สิ่งนี้จะไม่ระเบิด แต่ในหลายรูปแบบมันจะ เพิ่มสองสามไบต์ที่นี่และอาจมีการรั่วไหลสำหรับทุกสถานการณ์ อาจยกเว้นสวิตช์ไฟ

ทดสอบ

นี่คือชุดทดสอบ:

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

ผลลัพธ์หลังจาก 10 นาที:

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

นั่นคือ 2 684 476 624 ไบต์ กระบวนการทั้งหมดWorkingSetนั้นประมาณ 4.8 GB

คำตอบนี้ได้รับแรงบันดาลใจจากบทความที่ยอดเยี่ยม Eric Lippert ของ: เมื่อทุกอย่างที่คุณรู้ว่าเป็นสิ่งที่ผิด


นี่คือสิ่งที่น่าสนใจ คนเก็บขยะ "ลืม" ว่ามีบางอย่างอยู่และไม่ติดตามพวกเขาเพราะสิ่งนี้หรือไม่? ฉันไม่รู้มากเกี่ยวกับ c # นอกจากนี้ฉันยังสงสัยว่าอะไรคือความแตกต่างระหว่างระเบิดและการรั่วไหล ผมคิดว่าล้มเหลวที่คล้ายกันอาจจะสร้างขึ้นโดยการเรียกผู้สร้างจากด้านในของตัวสร้างหรือมีฟังก์ชั่น recursing อนันต์ที่ไม่เคยหยุดแม้ในทางเทคนิคระบบไม่เคยสูญเสียการติดตามของการอ้างอิงเหล่านั้นมันก็วิ่งออกไปจากพื้นที่ ...
ดอน สดใส

1
ตัวสร้างภายในตัวสร้างจะทำให้เกิดการล้นสแต็ค แต่ตัวทำลายของอินสแตนซ์ถูกเรียกในลำดับชั้นแบบเรียบ จริง ๆ แล้ว GC ไม่เคยสูญเสียการติดตามของวัตถุ เมื่อใดก็ตามที่มันพยายามทำลายพวกมันมันจะสร้างวัตถุใหม่โดยไม่รู้ตัว รหัสผู้ใช้ในทางกลับกันไม่สามารถเข้าถึงวัตถุดังกล่าว ความไม่สอดคล้องกันดังกล่าวอาจเกิดขึ้นเนื่องจาก GC อาจตัดสินใจที่จะทำลายวัตถุโดยไม่ต้องเรียก destructor
MrPaulch

จะไม่ท้าทายจะเสร็จสมบูรณ์โดยเพียงแค่ใช้class L{~L(){new L();}}? AFAIK for(;;)ทำให้หน่วยความจำรั่วเร็วขึ้นใช่มั้ย
BgrWorker

1
น่าเศร้าที่ไม่มี เนื่องจากสำหรับวัตถุที่ถูกทำลายแต่ละชิ้นจะมีเพียงหนึ่งอินสแตนซ์ใหม่เท่านั้นที่จะถูกสร้างขึ้นซึ่งจะไม่สามารถเข้าถึงได้และถูกทำเครื่องหมายเพื่อทำลาย ทำซ้ำ วัตถุเดียวเท่านั้นที่จะรอการทำลาย ไม่มีประชากรเพิ่มขึ้น
MrPaulch

2
ไม่ได้จริงๆ ในที่สุดหนึ่งก็สรุปจะถูกละเว้น วัตถุที่เกี่ยวข้องจะถูกกินโดยไม่คำนึงถึง
MrPaulch

26

C (gcc) , 15 ไบต์

f(){malloc(1);}

การตรวจสอบ

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

26

Javascript ขนาด 14 ไบต์

แข็งแรงเล่นกอล์ฟ

setInterval(0)

ลงทะเบียนตัวจัดการช่วงเวลาว่างด้วยการหน่วงเวลาเริ่มต้นโดยละทิ้งรหัสตัวจับเวลาผลลัพธ์ (ทำให้ไม่สามารถยกเลิกได้)

ป้อนคำอธิบายรูปภาพที่นี่

ฉันใช้ช่วงเวลาที่ไม่ใช่ค่าเริ่มต้นเพื่อสร้างตัวจับเวลาหลายล้านตัวเพื่อแสดงการรั่วไหลเช่นเดียวกับการใช้ช่วงเวลาเริ่มต้นกินซีพียูอย่างบ้าคลั่ง


5
ฮ่าฮ่าฉันรักที่คุณพิมพ์ 'Golfed' ทำให้ฉันอยากรู้เกี่ยวกับรุ่นที่ไม่ดี
Martijn

9
อาจมีลักษณะเช่นนี้if(window && window.setInterval && typeof window.setInterval === 'function') { window.setInterval(0); }
Tschallacka

3
ที่จริงแล้วมันเป็นไปไม่ได้ที่จะยกเลิก: ID ของช่วงเวลา (และการหมดเวลา) เป็นลำดับหมายเลขดังนั้นจึงค่อนข้างง่ายที่จะยกเลิกสิ่งต่าง ๆ เพียงแค่โทรclearIntervalด้วย ID ที่เพิ่มขึ้นจนกว่าช่วงเวลาของคุณจะหายไป ตัวอย่างเช่น:for(let i=0;i<1e5;i++){try{clearInterval(i);}catch(ex){}}
user2428118

5
@ user2428118 ตามที่ zeppelin กล่าวว่านี่ไม่ใช่ "legitmate" มากกว่าการพูดว่าการรั่วไหลของ C / C ++ ไม่ใช่ "ของจริง" เพราะคุณสามารถบังคับให้โทรหาคุณได้free()
TripeHound

1
ว้าวไม่ใช่ความท้าทายมากมายที่จาวาสคริปต์เป็นผู้แข่งขันจริง ...
Jared Smith

19

Java, 10 ไบต์

ในที่สุดคำตอบที่แข่งขันได้ใน Java!

แข็งแรงเล่นกอล์ฟ

". "::trim

นี่คือการอ้างอิงวิธีการ (เทียบกับค่าคงที่สตริง) ซึ่งสามารถใช้เช่นนั้น:

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

สตริงตัวอักษร". "จะถูกเพิ่มโดยอัตโนมัติไปยังพูลสตริงการฝึกงานแบบโกลบอลตามที่ดูแลโดยjava.lang.Stringชั้นเรียนและในขณะที่เราตัดแต่งทันทีการอ้างอิงถึงสตริงนั้นไม่สามารถนำกลับมาใช้ใหม่ในรหัสเพิ่มเติมได้ (เว้นแต่คุณจะประกาศสตริงเดียวกันซ้ำอีกครั้ง)

...

กลุ่มของสตริงที่ว่างเปล่าเริ่มแรกถูกเก็บรักษาไว้เป็นส่วนตัวโดยคลาสสตริง

สตริงตัวอักษรและนิพจน์ค่าคงที่สตริงทั้งหมดจะถูกฝึกงาน สตริงตัวอักษรถูกกำหนดไว้ในส่วน 3.10.5 ของข้อกำหนดภาษา Java ™

...

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

คุณสามารถเปลี่ยนสิ่งนี้ในหน่วยความจำรั่ว "เกรดการผลิต" โดยการเพิ่มสตริงให้กับตัวเองแล้วเรียกใช้วิธีการฝึกงาน ()อย่างชัดเจนในวง


2
ฉันพิจารณาสิ่งนี้สำหรับ C # ... แต่ฉันไม่คิดว่าจะนับเพราะคุณบอกว่าคุณสามารถเข้าถึงหน่วยความจำนั้นได้โดยการรวมสตริงตัวอักษรอื่น ฉันยังสนใจที่จะรู้ว่า("." + " ").intern()จะต้องทำอย่างไร (หากพวกเขาคือผู้ใช้ที่ป้อนเข้าหรือ w / e ดังนั้นเราจึงลดประสิทธิภาพของคอมไพเลอร์)
VisualMelon

1
ที่จริงฉันทามติเพียงอย่างเดียวที่ดีที่สุดฉันแค่มั่นในด้าน "รหัสควรรวบรวม" ฉันยังไม่แน่ใจว่าฉันซื้อการแก้ปัญหานี้ให้ถ้อยคำเกี่ยวกับคำถาม (สตริงเหล่านี้ไม่สามารถเป็นอิสระและพวกเขาสามารถพบได้ในรหัสเนินงานตามปกติแม้ว่ามันจะไม่น่า) แต่ผมขอเชิญคนอื่น ๆ ที่จะทำให้การตัดสินของตัวเอง
VisualMelon

3
สตริงนั้นไม่สามารถเข้าถึงได้แม้แต่ปล่อยให้อยู่คนเดียว เราสามารถเรียกดูได้ตลอดเวลาโดยการใช้สตริงที่เท่ากัน หากนับสิ่งนี้ตัวแปรโกลบอลที่ไม่ได้ใช้ (สแตติกส่วนตัวใน Java) จะเป็นรอยรั่ว นั่นไม่ใช่วิธีที่หน่วยความจำรั่ว
user2357112

3
@ user2357112 "... สตริงนั้นไม่สามารถเข้าถึงได้ ... " นั่นดูเหมือนจะชัดเจนเพราะคุณเห็นรหัส ตอนนี้ให้พิจารณาว่าคุณได้รับการอ้างอิงวิธีนี้ X () เป็นข้อโต้แย้งสำหรับรหัสของคุณคุณรู้ว่ามันจัดสรร (และฝึกงาน) สตริงตัวอักษรภายใน แต่คุณไม่ทราบว่าหนึ่งในนั้นอาจเป็น "." หรือ "123" หรือสตริงอื่น ๆ ของความยาวที่ไม่รู้จัก (โดยทั่วไป) คุณช่วยกรุณาแสดงให้เห็นว่าคุณยังสามารถเข้าถึงได้หรือยกเลิกการจัดสรรรายการในกลุ่ม "ฝึกงาน" ที่มันครอบครอง?
zeppelin

2
@ user2357112 บนเครื่องที่มีหน่วยความจำ จำกัด คุณสามารถเข้าถึงค่าที่เก็บไว้ในหน่วยความจำส่วนใดก็ได้simply by guessing it correctlyแต่นั่นไม่ได้หมายความว่าไม่มีหน่วยความจำรั่วไหล there's probably some way to use reflection to determine the string's contents tooคุณสามารถแสดงสิ่งนี้ได้ไหม (คำใบ้ String.intern () ถูกนำมาใช้ในพื้นเมือง code)
zeppelin

17

สนิม 52 ไบต์

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

จัดสรรบางไบต์ด้วยระบบ malloc สิ่งนี้ถือว่า ABI ที่ผิดนั้นเป็นที่ยอมรับได้


สนิม (ในทางทฤษฎี), 38 ไบต์

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

เราจัดสรรหน่วยความจำบนฮีปแยกตัวชี้แบบดิบแล้วก็ละเว้นมันรั่วอย่างมีประสิทธิภาพ ( Box::into_rawสั้นกว่าstd::mem::forget)

อย่างไรก็ตามสนิมโดยค่าเริ่มต้นใช้ jemalloc, ซึ่ง valgrind ไม่สามารถตรวจสอบการรั่วไหลใด เราสามารถสลับไปยังตัวจัดสรรระบบ แต่เพิ่ม 50 ไบต์และต้องการทุกคืน ขอบคุณมากสำหรับความปลอดภัยของหน่วยความจำ


ผลลัพธ์ของโปรแกรมแรก:

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

น่ากลัว โพสต์เช่นนี้ทำให้ฉันได้สำรวจสนิมในปีที่ผ่านมาซึ่งเป็นหนึ่งในภาษาที่สนุกที่สุดที่ฉันพยายามเรียนรู้
ดอนสดใส

16

8086 ASM, 3 ไบต์

ตัวอย่างนี้อนุมานว่ามีการเชื่อมโยง C runtime

jmp _malloc

แอสเซมบลีนี้ไปยังe9 XX XXที่XX XXอยู่ที่เกี่ยวข้องของ_malloc

สิ่งนี้เรียกใช้mallocเพื่อจัดสรรจำนวนหน่วยความจำที่คาดเดาไม่ได้จากนั้นส่งคืนทันทียุติกระบวนการ ในบางระบบปฏิบัติการเช่น DOS หน่วยความจำอาจไม่สามารถเรียกคืนได้เลยจนกว่าระบบจะรีบูต!


การใช้งานปกติของ malloc จะส่งผลให้หน่วยความจำที่เป็นอิสระเมื่อออกจากกระบวนการ
Joshua

@Joshua Yeah แต่นั่นเป็นพฤติกรรมการใช้งานที่กำหนดไว้
FUZxxl

12

ไปมา 6 ไบต์

แข็งแรงเล่นกอล์ฟ

s" " *

จัดสรรสตริงว่างด้วยs" "โดยปล่อยให้ที่อยู่และความยาว (0) อยู่ในสแต็กจากนั้นคูณพวกเขา (ทำให้ที่อยู่หน่วยความจำหายไป)

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

10

ไป 45 ไบต์

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

สิ่งนี้จะสร้าง goroutine นิรนามที่มีวนรอบไม่สิ้นสุด โปรแกรมสามารถทำงานต่อได้ตามปกติเนื่องจากการเริ่มต้น goroutine นั้นเหมือนกับการวางไข่เธรดขนาดเล็กที่รันพร้อมกัน แต่โปรแกรมไม่มีวิธีเรียกคืนหน่วยความจำที่จัดสรรให้กับ goroutine ตัวรวบรวมขยะจะไม่รวบรวมเลยตั้งแต่ยังทำงานอยู่ บางคนเรียกสิ่งนี้ว่า


ตรวจสอบกอล์ฟ: สั้นกว่าการโทร 2 ไบต์C.malloc(8)เนื่องจากคุณต้องimport"C"
Riking

9

Java 1.3, 23 ไบต์

void l(){new Thread();}

สร้างเธรด แต่ไม่เริ่มต้น เธรดได้รับการลงทะเบียนในเธรดพูลภายใน แต่จะไม่เริ่มต้นดังนั้นจึงไม่สิ้นสุดและไม่เคยเป็นผู้สมัครสำหรับ GC มันเป็นวัตถุที่ไม่สามารถแก้ไขได้ติดอยู่ใน Java limbos

เป็นข้อบกพร่องใน Java จนถึง 1.3 รวมอยู่ด้วยในขณะนั้นได้รับการแก้ไขในภายหลัง

การทดสอบ

โปรแกรมต่อไปนี้ทำให้แน่ใจว่าได้ทำให้หน่วยความจำสกปรกด้วยวัตถุเธรดใหม่และแสดงพื้นที่หน่วยความจำว่างที่ลดลง เพื่อการทดสอบการรั่วไหลฉันทำการทดสอบ GC อย่างเข้มข้น

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

เนื่องจากวิธีนี้ใช้งานได้เฉพาะกับรุ่น Java คุณควรพูดว่า "Java 3" ในส่วนหัวของคุณแทน

5
ไม่มีสิ่งเช่น Java 3 เป็น Java 1.3 มี Java 1.0, 1.1, 2, 1.3, 1.4, 5, 6, 7, 8, 9. หมายเลขแปลก แต่นั่นคือสิ่งที่มันเป็น
Olivier Grégoire

นี่คือความคิดของฉันด้วย ประณาม.
Magic Octopus Urn

8

Befunge ( เชื้อรา ) 1 ไบต์

$

นี่อาจขึ้นอยู่กับแพลตฟอร์มและขึ้นอยู่กับรุ่น (ฉันเพิ่งทดสอบกับรุ่น 1.0.4 บน Windows) แต่เชื้อราในอดีตเป็นล่ามที่รั่วมาก $(ลดลง) คำสั่งไม่ควรทำอะไรในกองว่างเปล่า แต่วนลูปกับรหัสนี้จัดการอย่างใดที่จะรั่วไหลหน่วยความจำมากอย่างรวดเร็ว ภายในไม่กี่วินาทีมันจะใช้เวลาสองสามกิ๊กและจะผิดพลาดด้วยข้อผิดพลาด "ออกจากหน่วยความจำ"

โปรดทราบว่ามันไม่จำเป็นต้องเป็น$คำสั่งเพียงเกี่ยวกับสิ่งที่จะทำ มันจะไม่ทำงานกับไฟล์ต้นฉบับที่ว่างเปล่า ต้องมีการดำเนินการอย่างน้อยหนึ่งครั้ง


8

สวิฟท์ 3, 38 ไบต์

เวอร์ชั่นใหม่:

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

x มีการอ้างอิงที่แข็งแกร่งกับตัวเองดังนั้นมันจะไม่ถูกจัดสรรคืนทำให้หน่วยความจำรั่ว

เวอร์ชั่นเก่า:

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

xมีการอ้างอิงที่แข็งแกร่งถึงyและในทางกลับกัน ดังนั้นจะไม่ถูกยกเลิกการจัดสรรทำให้หน่วยความจำรั่ว


อืมคุณยังคงสามารถอ้างอิงหน่วยความจำนั้นผ่านxและyดังนั้นนี่ไม่ได้ดูเหมือนรั่วจริง ๆ (ยกเว้นว่าคุณทำลายพวกเขาอย่างใด)
zeppelin

@zeppelin บรรทัดสุดท้ายสามารถห่อในฟังก์ชันเพื่อแก้ไขปัญหานั้น
NobodyNada

@NobodyNada ถ้าฉันจะใส่บรรทัดสุดท้ายในdoบล็อกที่จะแก้ไขปัญหาเหาะยกขึ้นใช่มั้ย?
แดเนียล

@Dopapp ใช่ doจะทำงานได้เป็นอย่างดี ความคิดที่ดี!
NobodyNada

มันสามารถย่อให้สั้นลงได้คุณไม่จำเป็นต้องมีสองคลาส - X สามารถอ้างอิงตัวเองได้:class X{var x: X!};do{let x=X();x.x=x}
Sebastian Osiński

7

Delphi (Object Pascal) - 33 ไบต์

การสร้างวัตถุโดยไม่มีตัวแปรโปรแกรมคอนโซลแบบเต็ม:

program;begin TObject.Create;end.

การเปิดใช้งาน FastMM4 ในโครงการจะแสดงการรั่วไหลของหน่วยความจำ:

ป้อนคำอธิบายรูปภาพที่นี่


6

C # - 84bytes

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

สิ่งนี้จะจัดสรรหน่วยความจำที่ไม่มีการจัดการ 1 ไบต์อย่างถูกต้อง IntPtrซึ่งฉันเชื่อว่าเป็นวิธีเดียวที่จะได้รับหรือปล่อยให้เป็นอิสระ คุณสามารถทดสอบได้โดยการบรรจุในลูปและรอให้แอปพลิเคชันหยุดทำงาน (อาจต้องการเพิ่มศูนย์สองสามตัวเพื่อเพิ่มความเร็วในการทำงาน)

ฉันพิจารณาSystem.IO.File.Create("a");แล้ว แต่ฉันไม่มั่นใจว่าสิ่งเหล่านี้จำเป็นต้องมีหน่วยความจำรั่วเนื่องจากแอปพลิเคชันเองจะรวบรวมหน่วยความจำมันเป็นระบบปฏิบัติการภายใต้ที่อาจรั่วไหล (เพราะCloseหรือDisposeไม่ถูกเรียก) สิ่งที่เข้าถึงไฟล์ยังต้องการสิทธิ์ระบบไฟล์และไม่มีใครต้องการที่จะพึ่งพาพวกเขา และมันกลับกลายเป็นว่าสิ่งนี้จะไม่รั่วไหลเลยเพราะไม่มีสิ่งใดที่จะหยุดการเข้ารอบสุดท้ายที่ถูกเรียก (ซึ่งเป็นอิสระจากทรัพยากรพื้นฐานที่เป็นไปได้) ซึ่งกรอบรวมถึงการลดข้อผิดพลาดในการตัดสิน (ระดับหนึ่ง) และ เพื่อสร้างความสับสนให้โปรแกรมเมอร์ด้วยการล็อคไฟล์ที่ดูเหมือนไม่ได้กำหนดไว้ (ถ้าคุณเป็นคนอื่น) ขอบคุณ Jon Hanna ที่ทำให้ฉันตรงไปตรงนี้

ฉันผิดหวังที่ไม่สามารถหาวิธีที่สั้นกว่านี้ได้ . NET GC ใช้งานได้ฉันไม่สามารถนึกถึงIDisposablesmscorlib ที่จะรั่วไหลได้อย่างแน่นอน(และแน่นอนว่าพวกเขาทั้งหมดมีผู้เข้ารอบสุดท้ายน่ารำคาญมาก)ฉันไม่รู้วิธีอื่นใดในการจัดสรรหน่วยความจำที่ไม่มีการจัดการ (ขาด PInvoke ) และสะท้อนให้มั่นใจได้อะไรกับการอ้างอิงถึงมัน (ไม่คำนึงถึงความหมายภาษา (เช่นสมาชิกส่วนตัวหรือชั้นเรียนที่มีไม่มี accessors)) สามารถพบได้


1
System.IO.File.Create("a")จะไม่รั่วไหล แต่GC.SuppressFinalize(System.IO.File.Create("a"))จะเป็นไปตามที่ได้รับการร้องขออย่างชัดเจนว่าจะไม่เรียกใช้ผู้เข้ารอบสุดท้ายของผู้FileStreamผลิต
Jon Hanna

@ จอนฮันเตอร์ค่อนข้างถูก ความหวาดระแวง IDisposable ของฉันดูเหมือนจะดีกว่าของฉัน
VisualMelon

คุณอาจมีโอกาสทำให้ GDI + รั่วไหลโดยใช้ System.Drawing.Bitmap ไม่ทราบว่านับหรือไม่เพราะเป็นห้องสมุด windows ที่ทำให้เกิดการรั่วไหลไม่ใช่ตัวโปรแกรมเอง
BgrWorker

@BgrWorker พวกเขาไม่ต้องสงสัยเลยว่ามีผู้ผ่านเข้ารอบสุดท้ายและฉันมักจะหลีกเลี่ยงห้องสมุดภายนอกใน code-golf เพราะฉันไม่เห็นด้วยกับฉันทามติเกี่ยวกับการคิดต้นทุนพวกเขา: หากคุณสามารถหาวิธีที่คุณมั่นใจในการโพสต์ ในคำตอบของคุณเอง!
VisualMelon

<!-- language: lang-c# -->ขอบคุณสำหรับคำตอบที่ดี & นี้! (มันคือ C # ดังนั้นฉันรักมัน)
Metoniem

5

ตัวคูณ 13 ไบต์

Factor มีการจัดการหน่วยความจำอัตโนมัติ แต่ยังให้การเข้าถึงฟังก์ชัน libc บางอย่าง:

1 malloc drop

จัดสรรหน่วยความจำ 1 ไบต์ด้วยตนเองส่งคืนที่อยู่และลดลง

malloc จริง ๆ แล้วการลงทะเบียนสำเนาเพื่อติดตามการรั่วไหลของหน่วยความจำและเพิ่มสองครั้ง แต่การระบุสิ่งที่คุณรั่วไหลไม่ใช่เรื่องง่าย

หากคุณต้องการตรวจสอบให้แน่ใจว่าคุณสูญเสียข้อมูลอ้างอิงนั้นจริงๆ:

1 (malloc) drop

การทดสอบการรั่วไหลด้วย[ 1 malloc drop ] leaks.พูดว่า:

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

การทดสอบการรั่วไหลด้วย[ 1 (malloc) drop ] leaks.พูดว่า:

| Disposable class | Instances | |

ไม่นะ! ปัจจัยแย่ตอนนี้มันเป็นโรคอัลไซเมอร์แล้ว! D:


5

Common Lisp (SBCL เท่านั้น) 28 26 ไบต์

sb-alien::(make-alien int)

คุณเรียกมันชอบโดย: sbcl --eval 'sb-alien::(make-alien int)'; ไม่มีการพิมพ์หรือส่งคืน แต่มีการจัดสรรหน่วยความจำเกิดขึ้น ถ้าฉันห่อแบบฟอร์มไว้ภายใน(print ...)ตัวชี้จะปรากฏใน REPL

  1. package::(form)เป็นสัญกรณ์พิเศษใน SBCL สำหรับผูกแพคเกจปัจจุบันชั่วคราวขณะที่อ่านฟอร์ม นี้จะใช้ที่นี่เพื่อหลีกเลี่ยงการ prefixing ทั้งสองmake-alienและมีint sb-alienฉันคิดว่ามันจะเป็นการโกงที่จะสมมติว่าแพ็คเกจปัจจุบันถูกตั้งค่าเป็นอันนี้เพราะนั่นไม่ใช่กรณีเริ่มต้น

  2. make-alien จัดสรรหน่วยความจำสำหรับประเภทที่กำหนดและขนาดที่เลือกได้ (โดยใช้ malloc)

  3. เมื่อเรียกใช้งานสิ่งนี้ใน REPL ให้เพิ่ม0หลังการจัดสรรเพื่อให้ REPL ไม่ได้คืนพอยน์เตอร์ แต่เป็นค่านั้นแทน มิฉะนั้นว่าไม่มีจะมีการรั่วไหลจริงเพราะ REPL จำสุดท้ายสามค่ากลับ (ดู*, **,*** ) และเราอาจจะยังคงมีโอกาสที่จะเป็นอิสระจัดสรรหน่วยความจำ

ลบออก 2 ไบต์ด้วยPrzemysławPขอบคุณ!


1
คุณไม่สามารถใช้1(หรือ2, 3ฯลฯ ) แทน()ค่าที่คุณส่งคืนได้1ใช่ไหม มันจะประหยัดได้ 1 ไบต์ ยังเป็นคำตอบนี้ REPL เท่านั้น? บางทีถ้าคุณโหลดรหัสด้วยloadคุณไม่สามารถรวม()หรืออะไรก็ได้ในตอนท้ายเพราะมันจะไม่สามารถเข้าถึงได้หรือไม่
PrzemysławP

1
@ PrzemysławPคุณพูดถูกทั้งสองข้อฉันลองด้วยevalและใช้งานได้ตามที่คุณพูด ขอบคุณมาก!
coredump

4

AutoIt , 39 ไบต์

#include<Memory.au3>
_MemGlobalAlloc(1)

จัดสรรหนึ่งไบต์จากฮีป เนื่องจากหมายเลขอ้างอิงที่ส่งคืนโดย_MemGlobalAllocถูกละทิ้งไม่มีวิธีใดที่จะทำให้การจัดสรรนั้นว่างอย่างชัดเจน


3

C ++, 16 ไบต์

main(){new int;}

ฉันไม่มี valgrind เพื่อตรวจสอบการรั่วไหล แต่ค่อนข้างแน่ใจว่าควร มิฉะนั้นฉันจะลอง:

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

ผลลัพธ์ Valgrind

(มันรั่วแน่นอน)

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

@Weateat ตัวช่วยสร้างที่ฉันกำลังใช้g++ 4.3.2(ไม่ใช่ตัวล่าสุด) และคอมไพล์ได้ดี intฉันไม่คิดว่าจะส่งคืนประเภทโดยปริยาย ด้วย-Wallฉันมีคำเตือนแม้ว่า:plop.cpp:1: warning: ISO C++ forbids declaration of 'main' with no type
matovitch

2
@WheatWizard ขออภัยฉันเพิ่งเห็นคุณให้ตัวอย่าง c ++ เพื่อเริ่มการแข่งขัน มาจาก reddit ฉันดูที่คำตอบเท่านั้นและ (แปลก) ไม่เห็น C ++ ฉันรู้สึกเป็นบิต : /
matovitch

ฉันทามติคือคุณสามารถนับได้[]{new int;}ว่าเป็นฟังก์ชัน C ++ (ความท้าทายไม่ได้ระบุโปรแกรมทั้งหมด)
Toby Speight

3

Java (OpenJDK 9) , 322 220 ไบต์

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

ลองออนไลน์!

นี่เป็นหน่วยความจำรั่วอื่น ๆ ที่ไม่ได้ใช้ String Cache มันจัดสรรครึ่งหนึ่งของ RAM ของคุณและคุณไม่สามารถทำอะไรกับมันได้

ขอบคุณ Zeppelin สำหรับการบันทึกไบต์ทั้งหมด


คุณสามารถบันทึกไบต์จำนวนมากได้โดยรับUnsafeอินสแตนซ์จากตัวแปรสแตติกข้างในนั้นเช่น: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

และคุณสามารถประหยัดได้มากขึ้นโดยการแทนที่public static void mainด้วย initializer แบบสแตติกstatic{try{}catch(Exception e){}}(ซึ่งอาจเป็นเรื่องยุ่งยากมากขึ้นในการเปิดตัว แต่ก็ใช้ได้จริงและสามารถคอมไพล์ได้)
zeppelin

yhea ใช้ตัวสร้างถูกใช้ในรหัส Android รุ่นที่ฉันใช้ ฉันจะเปลี่ยนบางสิ่งเมื่อฉัน im @ home แต่ฉันจะไปเส้นทางที่คุณไปด้วยคำสั่งเดียว;)
Serverfrog

ลบช่องว่างใช้aแทนargsและลบสาธารณะ tio.run/nexus/…
Pavel

true สามารถถูกแทนที่ด้วย 1> 0
masterX244

3

c, 9 ไบต์

main(){}

พิสูจน์:

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)

1
คุณไม่ได้รั่วหน่วยความจำจริงๆ gccคือ. สิ่งนี้ควรทำงานกับโปรแกรมเปล่า ลองgcc src.c && valgrind ./a.outซึ่งควรสร้างผลลัพธ์ที่สะอาด

3

C #, 109 ไบต์

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

เราพบแนวคิดเบื้องหลังการรั่วไหลของรหัสการผลิตและการวิจัยนำไปสู่บทความนี้ ปัญหาหลักอยู่ในคำพูดยาว ๆ จากบทความ (อ่านเพื่อรับข้อมูลเพิ่มเติม):

ค้นหารหัสของฉันเพื่อPurchaseOrdeหารหัสบรรทัดนี้ในpage_loadหน้าใดหน้าหนึ่งของฉันXmlSerializer serializer = new XmlSerializer(typeof(PurchaseOrder), new XmlRootAttribute(“”));

ดูเหมือนว่าจะเป็นโค้ดที่บริสุทธิ์ไร้เดียงสา เราสร้างสำหรับXMLSerializer PurchaseOrderแต่เกิดอะไรขึ้นภายใต้ฝาครอบ?

ถ้าเราดูคอนXmlSerializerสตรัคเตอร์ด้วย Reflector เราจะพบว่ามันเรียกสิ่งนั้นthis.tempAssembly = XmlSerializer.GenerateTempAssembly(this.mapping, type, defaultNamespace, location, evidence);ซึ่งสร้างชุดประกอบ temp (ไดนามิก) ดังนั้นทุกครั้งที่รหัสนี้ทำงาน (เช่นทุกครั้งที่มีการเข้าหน้า) มันจะสร้างชุดประกอบใหม่

เหตุผลที่สร้างแอสเซมบลีคือมันต้องการสร้างฟังก์ชันสำหรับซีเรียลไลซ์และดีซีเรียลไลซ์และสิ่งเหล่านี้จำเป็นต้องอยู่ที่ไหนสักแห่ง

โอเค…มันสร้างชุดประกอบแล้วอะไรนะ? เมื่อเราเสร็จแล้วก็ควรหายไปใช่มั้ย

อืม…การประกอบไม่ใช่วัตถุบน GC Heap, GC ไม่รู้การประกอบจริง ๆ ดังนั้นจึงไม่ได้รับการเก็บขยะ วิธีเดียวที่จะกำจัดชุดประกอบใน 1.0 และ 1.1 คือการยกเลิกการโหลดโดเมนแอพที่มีอยู่

และในนั้นปัญหาอยู่ที่ดร. วัตสัน

เรียกใช้จากคอมไพเลอร์ใน Visual Studio 2015 และการใช้หน้าต่างเครื่องมือวินิจฉัยแสดงผลลัพธ์ต่อไปนี้หลังจากนั้นประมาณ 38 วินาที หมายเหตุหน่วยความจำกระบวนการกำลังปีนอย่างต่อเนื่องและ Garbage Collector (GC) ยังคงทำงานต่อไป แต่ไม่สามารถรวบรวมอะไรได้

หน้าต่างเครื่องมือวินิจฉัย


2

C 30 ไบต์

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

ผลลัพธ์ของ Valgrind:

         ==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
เป็นไปได้ที่จะทำเช่นนั้นแทนmain(){malloc(1);}?
kirbyfan64sos

@ ใช่เลย! แต่มันถูกโพสต์แล้ว!
Abel Tom

2

โผ 76 ไบต์

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

เล็กน้อยเช่นคำตอบ JavaScript เมื่อคุณโทรหา.listenวัตถุ Dart stream คุณจะได้รับ StreamSubscription กลับซึ่งอนุญาตให้คุณยกเลิกการเชื่อมต่อจากสตรีม อย่างไรก็ตามหากคุณทิ้งไปคุณจะไม่สามารถยกเลิกการสมัครรับข้อมูลจากสตรีมทำให้เกิดการรั่วไหลได้ วิธีเดียวที่จะสามารถแก้ไขการรั่วไหลได้ก็คือถ้าตัวสตรีมได้รับการรวบรวม แต่ยังคงอ้างอิงภายในโดยคอมโบ StreamController + Timer

น่าเสียดาย Dart ฉลาดเกินไปสำหรับสิ่งอื่น ๆ ที่ฉันได้ลอง ()async=>await new Completer().futureไม่ทำงานเนื่องจากการใช้การรอคอยเหมือนกับการทำnew Completer().future.then(<continuation>)ซึ่งช่วยให้การปิดตัวเองถูกทำลายไม่ได้อ้างถึง Completer ตัวที่สอง (Completer มีการอ้างอิงถึงอนาคตจาก.futureอนาคต

นอกจากนี้ Isolates (aka threads) ได้รับการทำความสะอาดโดย GC ดังนั้นวางไข่ในหัวข้อใหม่และหยุดทันที (import'dart:isolate';main(_)=>Isolate.spawn(main,0,paused:true); ) ไม่ทำงาน แม้แต่วางไข่ไอโซเลทด้วยวงวนไม่สิ้นสุด ( import'dart:isolate';f(_){while(true){print('x');}}main()=>Isolate.spawn(f,0);) ฆ่าไอโซเลตและออกจากโปรแกรม

โอ้ดี


หากโปรแกรมหลักของคุณยังคงทำงานและทำสิ่งอื่น ๆ ตัวเก็บขยะจะสามารถหยุดการแยกได้หรือไม่ ฉันถามเพราะตัวอย่าง goroutine ของฉันฟังดูคล้ายกัน ... ฉันถือว่าความจริงที่ว่าโปรแกรมออกและให้หน่วยความจำทั้งหมดกลับไปที่ระบบปฏิบัติการไม่ได้แปลว่ามันไม่ได้รั่วไหล
ดอนสดใส

2

Swift ขนาด 12 ไบต์

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

คำอธิบาย:

นี่คือการรั่วไหลของหน่วยความจำโดยพฤตินัยที่สามารถเกิดขึ้นได้ในภาษาใด ๆ ไม่ว่าภาษานั้นจะใช้การจัดการด้วยตนเองของหน่วยความจำการนับการอ้างอิงอัตโนมัติ (ARC เช่น Swift) หรือแม้กระทั่งการกวาดเก็บขยะ

[3,5]เป็นเพียงอาร์เรย์ตัวอักษร อาร์เรย์นี้จัดสรรหน่วยความจำให้เพียงพอสำหรับองค์ประกอบ 2 อย่างน้อยเหล่านี้ 3และ5มีเพียงโดยพลการ

subscripting (การจัดทำดัชนี) ความผลิตArray<T> ArraySlice<T>An ArraySlice<T>เป็นมุมมองในหน่วยความจำของ Array ที่สร้างขึ้นจาก

[3,5][0...0]ก่อให้เกิดการมีค่าเป็นArraySlice<Int> [3]โปรดทราบว่า3ในส่วนนี้เป็น3องค์ประกอบเดียวกับ3ในต้นฉบับที่Arrayแสดงด้านบนไม่ใช่สำเนา

ชิ้นที่เกิดนั้นจะสามารถเก็บไว้ในตัวแปรและใช้ อาร์เรย์ดั้งเดิมไม่มีการอ้างอิงอีกต่อไปดังนั้นคุณอาจคิดว่ามันอาจถูกจัดสรรคืนได้ อย่างไรก็ตามมันไม่สามารถ

เนื่องจากชิ้นแสดงมุมมองไปยังหน่วยความจำของอาร์เรย์ที่มาจากอาร์เรย์เดิมจะต้องมีชีวิตอยู่ตราบเท่าที่ชิ้นยังมีชีวิตอยู่ ดังนั้นของ2ขนาดหน่วยความจำดั้งเดิมที่มีการจัดสรรจะมีการใช้เฉพาะขนาดหน่วยความจำแรกเท่านั้นส่วนอีกหน่วยหนึ่งจะต้องมีอยู่เพื่อไม่ให้จัดสรรหน่วยแรก องค์ประกอบขนาดที่สองของหน่วยความจำรั่วไหลออกมา

วิธีแก้ปัญหานี้คือการไม่เก็บอาร์เรย์ขนาดใหญ่ที่มีขนาดเล็กเป็นเวลานาน หากคุณต้องการคงเนื้อหาชิ้นไว้ให้เลื่อนไปยัง Array ซึ่งจะทำให้หน่วยความจำถูกคัดลอกดังนั้นจึงเป็นการลบการพึ่งพาหน่วยความจำของอาร์เรย์เดิม:

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

2

โซลูชันที่ 1: C (Mac OS X x86_64), 109 ไบต์

แหล่งที่มาสำหรับ golf_sol1.c

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

โปรแกรมข้างต้นจะต้องรวบรวมการเข้าถึงการดำเนินการในส่วน __DATA

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

จากนั้นเพื่อรันโปรแกรมให้เรียกใช้สิ่งต่อไปนี้:

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

ผล:

น่าเสียดายที่ Valgrind ไม่ได้มองหาหน่วยความจำที่จัดสรรจากการเรียกใช้ระบบดังนั้นฉันจึงไม่สามารถตรวจพบรอยรั่วที่ตรวจพบได้ดี

อย่างไรก็ตามเราสามารถดู vmmap เพื่อดูหน่วยความจำที่จัดสรรขนาดใหญ่ (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 

คำอธิบาย

ดังนั้นฉันคิดว่าฉันต้องอธิบายสิ่งที่เกิดขึ้นจริงที่นี่ก่อนที่จะไปสู่โซลูชันที่ได้รับการปรับปรุง

ฟังก์ชั่นหลักนี้ใช้ในการประกาศประเภทที่หายไปของ C (ดังนั้นจึงมีค่าเริ่มต้นเป็น int โดยที่เราไม่จำเป็นต้องเขียนอักขระเสีย) รวมถึงวิธีการทำงานของสัญลักษณ์ ตัวเชื่อมโยงนั้นสนใจว่าจะหาสัญลักษณ์mainที่โทรไปหาได้หรือไม่ ดังนั้นที่นี่เรากำลังสร้างอาร์เรย์หลักของ int ซึ่งเรากำลังเริ่มต้นด้วย shellcode ของเราที่จะถูกดำเนินการ ด้วยเหตุนี้หลักจะไม่ถูกเพิ่มลงในเซกเมนต์ __TEXT แต่เป็นเซกเมนต์ __DATA เหตุผลที่เราต้องคอมไพล์โปรแกรมด้วยเซ็กเมนต์ __DATA ที่สามารถเรียกใช้งานได้

shellcode ที่พบใน main มีดังต่อไปนี้:

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

สิ่งนี้กำลังทำอยู่คือเรียกใช้ฟังก์ชัน syscall เพื่อจัดสรรหน้าหน่วยความจำ (syscall mach_vm_allocate ใช้ภายใน) RAX ควรเท่ากับ 0x100000a (บอก syscall ว่าเราต้องการฟังก์ชั่นใด) ในขณะที่ RDI ถือเป้าหมายสำหรับการจัดสรร (ในกรณีของเราเราต้องการให้เป็น mach_task_self ()) RSI ควรเก็บที่อยู่เพื่อเขียนตัวชี้ไปยังหน่วยความจำที่สร้างขึ้นใหม่ (ดังนั้นเราแค่ชี้ไปที่ส่วนบนกองซ้อน) RDX ถือขนาดของการจัดสรร (เราเพิ่งผ่านใน RAX หรือ 0x100000a เพื่อบันทึกเป็นไบต์), R10 ถือธง (เราสามารถระบุได้ จัดสรรได้ทุกที่)

ตอนนี้ก็ไม่ชัดเจนว่า RAX และ RDI ได้รับค่าของพวกเขาจากที่ใด เรารู้ว่า RAX ต้องเป็น 0x100000a และ RDI ต้องเป็นค่า mach_task_self () ส่งคืน โชคดีที่ mach_task_self () เป็นแมโครจริงสำหรับตัวแปร (mach_task_self_) ซึ่งเป็นที่อยู่หน่วยความจำเดียวกันทุกครั้ง (ควรเปลี่ยนเมื่อทำการรีบูท) ในอินสแตนซ์เฉพาะของฉัน mach_task_self_ นั้นเกิดขึ้นที่ 0x00007fff7d578244 เพื่อลดคำแนะนำเราจะส่งผ่านข้อมูลนี้จาก argv แทน นี่คือเหตุผลที่เรารันโปรแกรมด้วยนิพจน์นี้$(ruby -e 'puts "\xf5\xff\xff\xfe\xff\xff\x44\x82\x57\x7d\xff\x7f"')สำหรับอาร์กิวเมนต์แรก สตริงคือค่าสองค่าที่รวมกันโดยที่ค่า RAX (0x100000a) มีเพียง 32 บิตและมีส่วนเสริมหนึ่งส่วนที่ใช้กับมัน (ดังนั้นจึงไม่มีค่าเป็นไบต์ว่างเราไม่ได้ค่าที่จะได้รับดั้งเดิม) ค่าถัดไปคือ RDI (0x00007fff7d578244) ซึ่งถูกเลื่อนไปทางซ้ายโดยเพิ่มขยะ 2 ไบต์เพิ่มไว้ที่ส่วนท้าย (อีกครั้งเพื่อไม่รวมไบต์ว่างเราเพียงแค่เลื่อนกลับไปทางขวาเพื่อให้กลับเป็นต้นฉบับ)

หลังจาก syscall เรากำลังเขียนไปยังหน่วยความจำที่จัดสรรใหม่ของเรา เหตุผลนี้เป็นเพราะหน่วยความจำที่จัดสรรโดยใช้ mach_vm_allocate (หรือ syscall นี้) เป็นหน้า VM จริงและไม่ได้ถูกเพจโดยอัตโนมัติในหน่วยความจำ ค่อนข้างจะถูกสงวนไว้จนกว่าข้อมูลจะถูกเขียนถึงพวกเขาแล้วหน้าเหล่านั้นจะถูกแมปลงในหน่วยความจำ ไม่แน่ใจว่าจะเป็นไปตามข้อกำหนดหรือไม่หากมีการจองไว้เท่านั้น

สำหรับวิธีแก้ไขปัญหาถัดไปเราจะใช้ประโยชน์จากความจริงที่ว่า shellcode ของเราไม่มีไบต์ว่างดังนั้นสามารถย้ายออกนอกรหัสโปรแกรมของเราเพื่อลดขนาด

โซลูชันที่ 2: C (Mac OS X x86_64), 44 ไบต์

แหล่งที่มาสำหรับ golf_sol2.c

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

โปรแกรมข้างต้นจะต้องรวบรวมการเข้าถึงการดำเนินการในส่วน __DATA

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

จากนั้นเพื่อรันโปรแกรมให้เรียกใช้สิ่งต่อไปนี้:

./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"')

ผลลัพธ์ควรเป็นเหมือนเดิมเนื่องจากเราทำการจัดสรรขนาดเดียวกัน

คำอธิบาย

ปฏิบัติตามแนวคิดเดียวกันกับโซลูชัน 1 โดยมีข้อยกเว้นว่าเราได้ย้ายโค้ดการรั่วไหลออกไปนอกโปรแกรม

shellcode ที่พบใน main ตอนนี้มีดังต่อไปนี้:

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

สิ่งนี้จะเป็นการคัดลอก shellcode ที่เราส่งผ่านใน argv ให้อยู่หลังรหัสนี้ (ดังนั้นหลังจากที่มันได้ทำการคัดลอกแล้วมันจะรัน shellcode ที่แทรกไว้) สิ่งที่เราโปรดปรานก็คือกลุ่ม __DATA จะมีขนาดหน้าอย่างน้อยที่สุดดังนั้นแม้ว่ารหัสของเราจะไม่ใหญ่เราก็สามารถเขียนได้อย่างปลอดภัยมากขึ้น ข้อเสียคือทางออกที่ดีที่สุดที่นี่ไม่จำเป็นต้องมีการคัดลอก แต่จะเรียกและดำเนินการ shellcode ใน argv โดยตรง แต่น่าเสียดายที่หน่วยความจำนี้ไม่มีสิทธิ์ดำเนินการ เราสามารถเปลี่ยนสิทธิ์ของหน่วยความจำนี้ได้อย่างไรก็ตามจะต้องใช้รหัสมากกว่าการคัดลอก กลยุทธ์ทางเลือกคือการเปลี่ยนสิทธิ์จากโปรแกรมภายนอก (แต่จะเพิ่มเติมในภายหลัง)

shellcode ที่เราส่งไปยัง argv มีดังต่อไปนี้:

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

นี่เหมือนกับโค้ดก่อนหน้าของเรามีความแตกต่างเพียงเพราะเรารวมถึงค่าสำหรับ EAX และ RDI โดยตรง

โซลูชันที่เป็นไปได้ 1: C (Mac OS X x86_64), 11 ไบต์

แนวคิดของการแก้ไขโปรแกรมจากภายนอกทำให้เรามีทางออกที่เป็นไปได้ในการย้าย leaker ไปยังโปรแกรมภายนอก ตำแหน่งที่โปรแกรมจริงของเรา (การส่ง) เป็นเพียงโปรแกรมจำลองและโปรแกรม leaker จะจัดสรรหน่วยความจำบางส่วนในโปรแกรมเป้าหมายของเรา ตอนนี้ฉันไม่แน่ใจว่าสิ่งนี้จะอยู่ภายในกฎสำหรับความท้าทายนี้ แต่การแบ่งปันนั้นยังคงอยู่

ดังนั้นหากเราต้องใช้ mach_vm_allocate ในโปรแกรมภายนอกโดยมีเป้าหมายที่ตั้งไว้ในโปรแกรมการท้าทายของเรานั่นอาจหมายถึงโปรแกรมการท้าทายของเราจะต้องมีอะไรบางอย่างในสายของ:

main=65259;

โดยที่ shellcode นั้นเป็นเพียงการกระโดดสั้น ๆ เพื่อตัวเอง (infinite jump / loop) ดังนั้นโปรแกรมยังคงเปิดอยู่และเราสามารถอ้างอิงได้จากโปรแกรมภายนอก

โซลูชันที่เป็นไปได้ 2: C (Mac OS X x86_64), 8 ไบต์

สนุกพอเมื่อฉันดูที่เอาต์พุต valgrind ฉันเห็นว่าอย่างน้อยตาม valgrind หน่วยความจำรั่ว ดังนั้นทุกโปรแกรมจึงมีหน่วยความจำรั่ว ด้วยกรณีนี้เราสามารถสร้างโปรแกรมที่ไม่ทำอะไรเลย (แค่ออก) และนั่นจะทำให้หน่วยความจำรั่ว

ที่มา:

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

2

ภาษาอังกฤษธรรมดา , 71 70 58 35 ไบต์

ลบ 1 ไบต์โดยการลบบรรทัดว่าง ลบ 12 ไบต์ด้วยการกำจัดคำจำกัดความประเภท "bogon" และใช้ชนิด "parent" parent แทนประเภทย่อย "bogon" ลบ 23 ไบต์โดยเปลี่ยนจากโปรแกรมที่สมบูรณ์เป็นเพียงขั้นตอนที่ทำให้หน่วยความจำรั่ว

รุ่น Golfed:

To x:
Allocate memory for a thing.

รุ่น Ungolfed ที่เป็นโปรแกรมที่สมบูรณ์ใช้นิยามย่อยและไม่รั่วไหลหน่วยความจำ:

A bogon is a thing.

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

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

หากเรียกรุ่น "x" golfed จะทำให้หน่วยความจำรั่วตามสัดส่วนจำนวนครั้งที่เรียกว่า "x" ในเวอร์ชัน golfed "จัดสรรคืนสิ่งที่" จะแก้ไขการรั่วไหลของหน่วยความจำ

ภาษาอังกฤษล้วนตรวจสอบการรั่วไหลของหน่วยความจำโดยค่าเริ่มต้น เมื่อรุ่นที่หน่วยความจำรั่วทำงานกล่องโต้ตอบจะปรากฏขึ้นก่อนที่โปรแกรมจะปิด กล่องโต้ตอบมีชื่อของ "debug" ข้อความของ "1 หยด" และปุ่ม "ตกลง" ยิ่งมีการเรียกฟังก์ชั่นการรั่วไหลมากขึ้นเท่าไหร่ข้อความก็จะยิ่งใหญ่ขึ้น เมื่อรุ่นที่ไม่มีการรั่วไหลของหน่วยความจำทำงานกล่องโต้ตอบจะไม่ปรากฏขึ้น

ในภาษาอังกฤษธรรมดา "สิ่ง" เป็นตัวชี้ไปยังรายการในรายการที่เชื่อมโยงเป็นสองเท่า "Thing", "to start up" และ "to shut down" ถูกกำหนดไว้ในโมดูลที่เรียกว่า "the noodle" ซึ่งจะต้องคัดลอก (โดยปกติจะเป็นไฟล์แยกต่างหาก) ในแต่ละโครงการ "A", "the", "ถึง", "เพื่อจัดสรรหน่วยความจำ" และ "to destroy" ถูกกำหนดในคอมไพเลอร์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.