สร้างการรั่วไหลของหน่วยความจำโดยไม่มีการทิ้งระเบิดใด ๆ [ปิด]


54

งานของคุณคือการสร้างหน่วยความจำรั่ว นี่คือโปรแกรมที่ใช้โหลดหน่วยความจำจนกระทั่งคอมพิวเตอร์หมดและต้องทำการสลับบางอย่างเพื่อบันทึกตัวเองไม่ให้หมด วิธีเดียวที่หน่วยความจำสามารถปล่อยออกมาได้ก็คือการฆ่าโปรแกรมในตัวจัดการงานหรือการใช้บรรทัดคำสั่งฆ่าเช่นtaskkill /im yourprogram /f(ใน Windows) หรือแม้กระทั่งการรีสตาร์ทคอมพิวเตอร์ การปิดแอพเพียงอย่างเดียวไม่ควรป้องกันแอพนี้ต่อไปยังหน่วยความจำหมู

กฎ:

  1. ห้ามทำการทิ้งระเบิดทุกประเภท นั่นหมายความว่าห้ามใช้Bash line :(){ :|:&};:!

  2. แอปพลิเคชันต้องเป็นแบบเธรดเดียวเท่านั้น นี่หมายถึงกฎส้อมระเบิด

  3. โปรแกรมต้องไม่เรียกใช้โปรแกรมอื่น หมายความว่าคุณไม่สามารถทำอะไรrun(memoryfiller.exe)ได้ ข้อยกเว้นเพียงอย่างเดียวคือโปรแกรมที่มาพร้อมกับระบบปฏิบัติการหรือภาษาของคุณซึ่งไม่ได้ออกแบบมาเพื่อใช้หน่วยความจำ (เช่นมีวัตถุประสงค์อื่น) ซึ่งหมายความว่าสิ่งที่ชอบcatและln -sได้รับอนุญาต

  4. คุณสามารถใช้หน่วยความจำได้มากเท่าที่คุณต้องการ ยิ่งมากยิ่งดี

  5. ต้องอธิบายรหัสอย่างครบถ้วน

โชคดี. นี่คือการประกวดความนิยมดังนั้นรหัสที่มีคะแนนโหวตมากที่สุดหลังจาก 10 วันนับจากวันที่ถามจะเป็นผู้ชนะ!


8
"การปิดจะยังทำให้หน่วยความจำ hog" - หากโปรแกรมทำงานได้กับเชลล์ (เช่นโปรแกรมแปลภาษาสคริปต์ส่วนใหญ่ของ windows) การปิดหน้าต่างจะเป็นการฆ่าโปรแกรม
mniip

54
นี่มันไม่ใช่while(1)malloc(999);เหรอ?
Doorknob

10
ฉันไม่แน่ใจว่า "การปิดยังควรทำให้หน่วยความจำหมู" เข้ากันได้กับ "แอปพลิเคชันจะต้องเป็นเธรดเดียวเท่านั้น" หากเธรดไม่มีหน่วยความจำอันใดอันหนึ่ง OS สามารถนำกลับมาใช้ได้ไหม?
aebabis

51
เพียงเรียกใช้ firefox 26 ด้วยแท็บเปิดแฟลชที่เปิดอยู่สองสามชั่วโมง มันจะนำคอมพิวเตอร์ของคุณไปที่หัวเข่า
Braden Best

1
@mniip นั่นคือจุดรวมของความท้าทาย เพื่อสร้างความท้าทายที่ยาก และลูกบิดประตู ฉันต้องการสิ่งที่แตกต่าง! ;)
George

คำตอบ:


78

ของ windows

Win32 API ช่วยให้คุณสามารถจัดสรรหน่วยความจำในกระบวนการอื่นและจากนั้นอ่าน / เขียนหน่วยความจำนั้นจากระยะไกล โปรแกรมนี้มีเธรดเดียวเท่านั้นซึ่งจะใช้เพื่อระบุแต่ละกระบวนการที่กำลังทำงานอยู่บนระบบและจากนั้นปันส่วนบัฟเฟอร์ 1MB ซ้ำ ๆ กันในแต่ละกระบวนการจนกระทั่งการจัดสรรล้มเหลว เมื่อมันเสร็จสิ้นด้วยกระบวนการเดียวมันจะไปยังกระบวนการถัดไป การจัดสรรจะไม่ถูกนำออกใช้เมื่อโปรแกรมการเรียกเสร็จสิ้น - เฉพาะเมื่อ / หากกระบวนการเป้าหมายแต่ละกระบวนการเสร็จสิ้น การทำเช่นนี้จะทำให้ VM ของ Windows 7 2GB หยุดทำงานในเวลาประมาณ 10 วินาที มันต้องการการทำงานในฐานะผู้ดูแลระบบ

เพื่อรวบรวม: cl /MD leak.cpp /link psapi.lib

#include <windows.h>
#include <psapi.h>

typedef void (*ProcFunc)(DWORD pid);
#define ALLOC_SIZE 0x100000
LPVOID buf;

void ForEachProcess(ProcFunc f)
{
    DWORD aProcesses[1024], cbNeeded;

    if (!EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded))
        return;

    for (unsigned int i = 0; i < cbNeeded / sizeof(DWORD); i++)
        if (aProcesses[i] != 0)
            f(aProcesses[i]);
}

void RemoteLeak(DWORD pid)
{
    HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid );
    if (hProcess == NULL)
        return;

    for (;;)
    {
        LPVOID ptr = VirtualAllocEx(hProcess, NULL, ALLOC_SIZE, 
                                    MEM_COMMIT, PAGE_READWRITE);
        if (ptr == NULL)
            return;

        WriteProcessMemory(hProcess, ptr, buf, ALLOC_SIZE, NULL);
    }
}

int main(void)
{
    buf = malloc(ALLOC_SIZE);
    if (buf == NULL)
        return 0;

    memset(buf, 0xFF, ALLOC_SIZE);

    ForEachProcess(RemoteLeak);

    return 0;
}

9
Windows นั้นชั่วร้าย
tomsmeding

4
ฉันต้องปิดตัวลงในคืนนี้ อย่าไปทำแบบนี้;)
George

1
"(ทำงานในฐานะผู้ใช้ปกติไม่ได้ใช้สิทธิ์ผู้ดูแลระบบ" - ไม่แน่ใจเกี่ยวกับเรื่องนี้คุณต้อง SeDebugPrivilege ซึ่งโดยค่าเริ่มต้นจะไม่ปรากฏในโทเค็นของผู้ใช้ทั่วไป
rkosegi

@rkosegi ขอบคุณคง
Andrew Medico

14
+1 สิ่งนี้สมควรได้รับการยกระดับมากเนื่องจากมันเป็นคำตอบเดียวที่ตรงกับการปิดแบบดั้งเดิมมันควรจะทำให้ความต้องการหน่วยความจำของหมูเป็นจริง โซลูชันที่สร้างสรรค์มาก :-)
Daniel

72

ชวา

import java.util.concurrent.atomic.AtomicInteger;

public class Hydra {
  // Not actually necessary for the leak - keeps track of how many Hydras there are, so we know when they're all gone
  public static AtomicInteger count = new AtomicInteger(0);
  public Hydra() {
    count.incrementAndGet();
  }
  protected void finalize() {
    new Hydra();
    new Hydra();
    count.decrementAndGet();
  }

  public static void main(String[] args) throws InterruptedException {
    new Hydra();
    while (Hydra.count.get() > 0) {
      // Prevent leaks ;-)
      System.gc();
      System.runFinalization();
    } 
  }
}

คำอธิบาย

คุณอาจคิดว่าเนื่องจากไม่มีการอ้างอิงในรหัส (นอกเหนือจากcountที่คุณสามารถละเว้นได้อย่างปลอดภัย) จึงไม่สามารถรั่วไหลได้ อย่างไรก็ตามตัวสร้างขั้นสุดท้ายสร้าง Hydras ใหม่สองตัวและแม้ว่ามันจะไม่มีการอ้างอิงสำหรับสิ่งเหล่านี้ ซึ่งหมายความว่าโปรแกรมเฉพาะการรั่วไหลของหน่วยความจำในระหว่างการเก็บขยะ - เพราะฉะนั้นสายไปและSystem.gc()System.runFinalization()


7
@TimS ตอนนี้พระเจ้าของคุณอยู่ที่ไหน!
Cruncher

มีSystem.gc()และSystem.runFinalization()จำเป็น? gc นั้นจะทำงานแบบสุ่มในบางครั้งหรือคุณต้องเติมหน่วยความจำหรือโทร gc?
Cruncher

4
ในโปรแกรมทั่วไปSystem.gc()และSystem.runFinalization()ไม่จำเป็น การรวบรวมขยะจะเกิดขึ้นตามธรรมชาติเนื่องจากความดันหน่วยความจำ อย่างไรก็ตามในแอปพลิเคชันนี้ไม่มีแรงกดดันด้านหน่วยความจำจนกว่าการรวบรวมขยะจะเริ่มทำงาน ฉันคิดเกี่ยวกับการแนะนำสิ่งประดิษฐ์ (ตัวอย่างเช่นโดยการเคลื่อนไหวnew Hydra()ภายในวง) แต่คิดว่านี่เป็นสิ่งที่ชั่วร้ายกว่า
James_pic

1
ใช่ฉันไม่ได้สนใจอะไรมากกับ "การปิดมันควรจะทำให้มันเป็นความทรงจำของหมู" เนื่องจากมันไม่ได้มีความหมาย (นอกเหนือจากแฮ็คระบบปฏิบัติการที่เรียบร้อยเช่น @ german_guy) Java หมุนวนเธรดการสรุปสุดท้ายเสมอดังนั้นอาจไม่มีวิธีใดที่แอปพลิเคชัน Java จะเชื่อฟังกฎ # 2
James_pic

1
บนระบบ Unix คุณไม่สามารถบล็อก SIGKILL (สัญญาณ 9) ดังนั้นคุณจึงไม่สามารถทำให้โปรแกรมของคุณไม่สามารถหยุดการทำงานได้ (ดียกเว้นถ้าคุณจัดการเพื่อให้มันเข้าสู่สถานะที่ไม่สามารถขัดจังหวะการรอ ... ดังนั้นอาจฆ่าเซิร์ฟเวอร์ NFS การเข้าถึงอาจทำงานได้ ;-))
celtschk

37

C

การใช้ภาษาการเขียนโปรแกรม C และทดสอบกับ Linux kernel 2.6.32-49-generic และ libc-2.11.1.so

วิธีเดียวที่หน่วยความจำสามารถปล่อยออกมาได้ก็คือการฆ่าโปรแกรมในตัวจัดการงานหรือใช้ taskkill / im yourprogram / f หรือแม้แต่การรีสตาร์ทพีซี

สิ่งนี้สามารถทำได้โดยการปิดกั้นสัญญาณใด ๆ ยกเว้น SIGKILL และ SIGSTOP

การปิดมันยังทำให้หน่วยความจำหม่นหมอง

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

ห้ามทำการทิ้งระเบิดทุกประเภท นั่นหมายความว่าทุบตีที่น่าอับอาย: () {: |: &} ;: ถูกแบน!

กระบวนการไม่แยก

แอปพลิเคชันต้องเป็นเธรดเดี่ยวเท่านั้น นี่แสดงถึงกฎการวางระเบิด

ไม่มีเธรดใหม่เกิดขึ้น

โปรแกรมต้องไม่เรียกใช้โปรแกรมอื่น ซึ่งหมายความว่าคุณไม่สามารถทำบางสิ่งเช่นเรียกใช้ (memoryfiller.exe)

ไม่มีกระบวนการใหม่เกิดขึ้น

คุณสามารถใช้หน่วยความจำได้มากเท่าที่คุณต้องการ ยิ่งมากยิ่งดี

มากที่สุดเท่าที่ระบบปฏิบัติการสามารถให้ได้

ต้องอธิบายรหัสอย่างครบถ้วน

เพิ่มความคิดเห็นไปยังแหล่งที่มา

และสุดท้ายนี่คือรหัส:

#define _GNU_SOURCE

#include <stdio.h>
#include <signal.h>
#include <sys/resource.h>
#include <unistd.h>
#include <stdlib.h>


int main(int argc, char* argv[]) {

    /*
    set the real, effective and set user id to root,
    so that the process can adjust possible limits.
    if the process doesn't have the CAP_SETUID capability, terminate the process.
    */
    if (setresuid(0, 0, 0) == -1) {
        printf("Are you root?!\n");
        return 1;
    }

    /*
    block all signals except for kill and stop.
    this allows to terminate the parent process (most likely a terminal)
    that this process is running in and turn it into a daemon.
    additionally this makes it impossible to terminate the process
    in a normal way and therefore satisfies the requirement that closing
    it should still make it hog memory.
    */
    sigset_t mask;
    sigfillset(&mask);
    sigprocmask(SIG_SETMASK, &mask, NULL);

    /*
    allow the process to acquire a virtually unlimited amount of memory
    and queue a virtually unlimited amount of signals.
    this is to prevent an out of memory error due to a virtual limit for the root user,
    which would prevent the process from leaking any more memory
    and to prevent the process from getting killed due to too many queued
    signals that the process is blocking.
    */
    struct rlimit memory = { RLIM_INFINITY, RLIM_INFINITY },
                  signal = { RLIM_INFINITY, RLIM_INFINITY};
    setrlimit(RLIMIT_AS, &memory);
    setrlimit(RLIMIT_SIGPENDING, &signal);

    /*
    allocate a buffer big enough to store a file name into it
    that is generated from the process' pid.
    if the file can be opened (which should always be the case unless /proc is not mounted)
    the file will be opened and the string -17 followed by a new line written to it.
    this will cause the oom killer to ignore our process and only kill other,
    innocent processes when running out of memory.
    */
    char file_name[20];
    sprintf(file_name, "/proc/%u/oom_adj", getpid());

    FILE* oom_killer_file = fopen(file_name, "w");
    if (oom_killer_file) {
        fprintf(oom_killer_file, "-17\n");
        fclose(oom_killer_file);
    }

    /*
    get the size of virtual memory pages in bytes,
    so the process knows the size of chunks that have to be
    made dirty to force the kernel to map the virtual memory page into RAM.
    */
    long page_size = sysconf(_SC_PAGESIZE);

    // allocate a virtually infinite amount of memory by chunks of a page size.
    while(1) {
        // will overwrite any previous stored address in tmp, leaking that memory.
        char* tmp = (char*) malloc(page_size);
        if (tmp)
            // make the memory page dirty to force the kernel to map it into RAM.
            tmp[0] = 0;
    }

    return 0;
}

สำหรับทุกคนที่สนใจว่าจะเกิดอะไรขึ้นถ้าคุณยังคงให้โปรแกรมทำงานต่อไปนี้: ในระบบทดสอบของฉันที่มีพื้นที่หน่วยความจำ 2GB และพื้นที่สว็อป 4GB ใช้เวลาประมาณ 10 นาทีในการเติมแรมและสว็อป นักฆ่า OOM เริ่มทำงานและอีกสามนาทีต่อมากระบวนการทั้งหมดก็ถูกฆ่า แม้แต่ระบบเม้าส์, คีย์บอร์ดและจอแสดงผลก็ถูกทิ้ง /var/log/kern.log ไม่แสดงข้อมูลที่เป็นประโยชน์ยกเว้นกระบวนการที่ถูกฆ่า


ฉันแก้ไขซอร์สเพื่อให้ตัวทำลาย oom ไม่สนใจกระบวนการและฆ่ากระบวนการที่ไร้เดียงสาเพื่อเพิ่มหน่วยความจำแทน
foobar

5
สำหรับทุกคนที่สนใจว่าจะเกิดอะไรขึ้นถ้าคุณยังคงให้โปรแกรมทำงานต่อไปนี้: ในระบบทดสอบของฉันที่มีพื้นที่หน่วยความจำ 2GB และพื้นที่สว็อป 4GB ใช้เวลาประมาณ 10 นาทีในการเติมแรมและสว็อป นักฆ่า OOM เริ่มทำงานและอีกสามนาทีต่อมากระบวนการทั้งหมดก็ถูกฆ่า แม้แต่ระบบเม้าส์, คีย์บอร์ดและจอแสดงผลก็ยังตกหล่น /var/log/kern.log ไม่แสดงข้อมูลที่เป็นประโยชน์ยกเว้นกระบวนการที่ถูกฆ่า
foobar

ฮ่าฮ่าเยี่ยมมาก! คุณควรแก้ไขคำอธิบายนั้นเป็นคำตอบของคุณ +1
Doorknob

1
ฉันไม่ได้ลงคะแนน แต่มันจะดีถ้ารหัสสามารถจัดรูปแบบจึงไม่จำเป็นต้องเลื่อนแนวนอนเพื่ออ่านความคิดเห็น
Paŭlo Ebermann

2
+1 สำหรับ 1) ทำให้กระบวนการส่งมอบอุปกรณ์อินพุต / เอาต์พุตให้ถูกฆ่าและ 2) การสร้างโปรแกรมที่ยากต่อการติดตามจากบันทึก นี่คือระดับของความชั่วร้าย
Kevin

29

Pure Bash

ไม่ใช่การแยกระเบิดฉันสัญญาว่า:

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

มันดูคล้ายกับ fork bomb และใช้เทคนิค recursive แบบเดียวกัน แต่ไม่มีส้อม แน่นอนว่าสิ่งนี้จะทำให้เชลล์ของคุณหมดหน่วยความจำดังนั้นคุณควรที่จะเริ่มเชลล์ใหม่ก่อนที่จะวางคำสั่งนี้

  • กำหนดฟังก์ชั่นที่เรียกว่า :
  • ฟังก์ชั่นเพียงเรียกซ้ำตัวเองด้วย$@(รายการ ARG) สองเท่า
  • หลังจากนิยามฟังก์ชันแล้ว:ฟังก์ชันจะถูกเรียกด้วย arg เริ่มต้น:

เอาท์พุท:

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

ในการแก้ไขคำตอบก่อนหน้านี้ที่ฉันทำa=$(yes)แต่ฉันสังเกตเห็นกฎ "โปรแกรมจะต้องไม่เรียกใช้โปรแกรมอื่น" ดังนั้นฉันต้องใช้บริสุทธิ์bashแทนโดยไม่ต้องเรียก coreutils ใด ๆ หรือสิ่งอื่นใด


นี่คืออีกหนึ่ง:

โปรดอย่าใช้สิ่งนี้กับเครื่องจักรผลิต

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

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

เช่นเดียวกับใน fork fork bomb :()จะมีการกำหนดฟังก์ชันแบบเรียกซ้ำ อย่างไรก็ตามจะไม่แยกการโทรออกไปยังตัวเอง แต่มันเรียกตัวเองด้วยอาร์กิวเมนต์เดียวซึ่งเป็นตัวเองที่เรียกว่าในเปลี่ยนตัวกระบวนการ เนื่องจากการทดแทนกระบวนการทำงานโดยการเปิดไฟล์ descriptor /dev/fd/nซึ่งไม่เพียง แต่กินหน่วยความจำ process (bash) เท่านั้นมันยังกินหน่วยความจำเคอร์เนลด้วยเช่นกัน บนเครื่อง Ubuntu ของฉันสิ่งนี้มีผลในการทำให้ตัวจัดการหน้าต่างไม่สามารถใช้งานได้หลังจากผ่านไปไม่กี่วินาทีจากนั้นก็จบลงด้วยหน้าจอนี้:

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

คลิกOKแล้วให้หน้าจอนี้:

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

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


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

2
"วิธีเดียวที่หน่วยความจำจะถูกปล่อยออกมาก็คือการฆ่าโปรแกรมในตัวจัดการงานหรือใช้โปรแกรม taskkill / im yourprogram / f หรือแม้แต่การรีสตาร์ทพีซี >> ทุบตีสามารถยกเลิกได้โดยใช้ SIGTERM ดังนั้นการฆ่ามันไม่จำเป็นต้องหยุดทำงาน นอกจากนี้ยังหยุดทำงานเมื่อระบบหน่วยความจำไม่เพียงพอ เมื่อ bash ถูกยกเลิกโดย SIGTERM หรือหน่วยความจำไม่เพียงพอหน่วยความจำจะถูกส่งกลับไปยังระบบปฏิบัติการ
foobar

สิ่งนี้ใช้ไม่ได้สำหรับฉัน ... การเรียงลำดับของ ... ฉันสามารถเห็นความทรงจำค่อย ๆ เลือนหายไป แต่สิ่งนี้เกิดขึ้นช้ามากและมันสามารถถูกฆ่าได้โดยกด ctrl + c ใช้งานได้ 1 นาทีและใช้งานได้ประมาณ 1GB ฉันมีเครื่องจักรเร็วมาก ... แต่นั่นไม่ควรสำคัญใช่ไหม
Stefanos Kalantzis

ตอบกลับความคิดเห็นของฉัน: คำสั่งจริงฆ่าทุบตีหลังจากประมาณ 2 นาที 49 วินาที ตอนแรกฉันคิดว่ามันจะขึ้นอยู่กับคำตอบนี้ทันที
Stefanos Kalantzis

@StefanosKalantzis ขอบคุณสำหรับความคิดเห็นของคุณ มันทำให้ฉันคิดมากขึ้นและฉันเพิ่งพบตัวอย่างกระสุนชั่วร้ายยิ่งขึ้น - ดูการแก้ไข
Digital Trauma

24

XML

<!DOCTYPE boom [
<!ENTITY Z 'ka-boom!'><!ENTITY Y '&Z;&Z;'><!ENTITY X '&Y;&Y;'><!ENTITY W '&X;&X;'>
<!ENTITY V '&W;&W;'><!ENTITY U '&V;&V;'><!ENTITY T '&U;&U;'><!ENTITY S '&T;&T;'>
<!ENTITY R '&S;&S;'><!ENTITY Q '&R;&R;'><!ENTITY P '&Q;&Q;'><!ENTITY O '&P;&P;'>
<!ENTITY N '&O;&O;'><!ENTITY M '&N;&N;'><!ENTITY L '&M;&M;'><!ENTITY K '&L;&L;'>
<!ENTITY J '&K;&K;'><!ENTITY I '&J;&J;'><!ENTITY H '&I;&I;'><!ENTITY G '&H;&H;'>
<!ENTITY F '&G;&G;'><!ENTITY E '&F;&F;'><!ENTITY D '&E;&E;'><!ENTITY C '&D;&D;'>
<!ENTITY B '&C;&C;'><!ENTITY A '&B;&B;'><!ENTITY z '&A;&A;'><!ENTITY y '&z;&z;'>
<!ENTITY x '&y;&y;'><!ENTITY w '&x;&x;'><!ENTITY v '&w;&w;'><!ENTITY u '&v;&v;'>
<!ENTITY t '&u;&u;'><!ENTITY s '&t;&t;'><!ENTITY r '&s;&s;'><!ENTITY q '&r;&r;'>
<!ENTITY p '&q;&q;'><!ENTITY o '&p;&p;'><!ENTITY n '&o;&o;'><!ENTITY m '&n;&n;'>
<!ENTITY l '&m;&m;'><!ENTITY k '&l;&l;'><!ENTITY j '&k;&k;'><!ENTITY i '&j;&j;'>
<!ENTITY h '&i;&i;'><!ENTITY g '&h;&h;'><!ENTITY f '&g;&g;'><!ENTITY e '&f;&f;'>
<!ENTITY d '&e;&e;'><!ENTITY c '&d;&d;'><!ENTITY b '&c;&c;'><!ENTITY a '&b;&b;'>
]>
<boom a="&a;"/>

จากนั้นส่งเอกสารไปยังตัวแยกวิเคราะห์ XML ที่ไม่ทำการตรวจสอบการอ้างอิงเอนทิตีวนลูป / การเรียกซ้ำ ตัวอย่างเช่นxpathรวมอยู่ใน perl:

xpath boom.xml /

มันทำงานอย่างไร:

  1. โปรแกรมแยกวิเคราะห์พบ <boom a="&a;">
  2. โปรแกรมแยกวิเคราะห์ขยาย"&a;"ออก"&b;&b;"
  3. parser ขยายหนึ่งใน"&b;"เข้า"&c;&c;"(เมื่อกลับมามันจะขยายอื่น ๆ"&b;")
  4. โปรแกรมแยกวิเคราะห์ขยายหนึ่งใน"&c;"...

หากการขยายเต็มอาจเกิดขึ้นจะมีการขยาย 2 "52" ka-boom! " สมมติว่า 2 ไบต์ต่อตัวอักษรก็จะพยายามใช้ 64 PiB การขยายตัวไปสู่ ​​"Ka-boom!" ในแต่ละครั้งดังนั้นคุณจะสามารถดูได้โดยใช้หน่วยความจำทั้งหมดที่อยู่ด้านบน

นี่เป็นชื่อต่าง ๆ ภาพรวมดีที่นี่: http://projects.webappsec.org/w/page/13247002/XML%20Entity%20Expansion



@ ColeJohnson Yup นั่นแหละ! ฉันมีส่วนร่วมในโครงการการจำแนกประเภทภัยคุกคามของ WASC ดังนั้นฉันรู้สึกว่ามีความมุ่งมั่นที่จะชี้ไปที่ WASC มากกว่าวิกิพีเดีย :)
uroeuroburɳ

22

C ++

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

รหัสนี้ไม่คาดคิด! มันแขวนคอมพิวเตอร์ของฉันในขณะที่ตัวจัดการงานเปิดและแสดงว่าใช้หน่วยความจำ 890 Mb ใน 1 วินาทีจากนั้นก็แขวน ฉันไม่รู้ว่ามันใช้งานได้อย่างไรบางทีมันก็ยังคงให้หน่วยความจำกับตัวแปรเพื่อสำรวจรหัสนี้มากขึ้นฉันได้เพิ่มคำสั่งdelete a;และทุกอย่างเรียบร้อยในขณะที่ทดสอบ (ไม่แขวน) ดังนั้นฉันคิดว่าหน่วยความจำอันนั้น ได้รับ (เนื่องจากnew int) แล้วนำกลับมา (เนื่องจากdelete a) ไปยังพื้นที่ว่างในรหัสใหม่ด้านล่าง

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

ดังนั้นฉันจึงสรุปได้ว่าไม่มี RAM ในโลกนี้ที่สามารถจัดการรหัสนี้ได้ !!!

แก้ไข : แต่โปรเซสเซอร์จำนวนมากสามารถสำหรับเช่นintel core 2 duoไม่สามารถจัดการรหัสนี้ แต่
intel core i-seriesสามารถ (ทำงานได้สำหรับฉัน ... )

โปรดจำไว้ว่าคำตอบของคำถามคือรหัสที่หนึ่งข้อที่สองสำหรับคำอธิบาย


9
นิสัยดีคอมไพเลอร์คิดว่าคุณยังคงใช้งานnew intได้แม้ว่าคุณจะเขียนทับตัวชี้ดังนั้นคุณจึงไม่สามารถเข้าถึงได้อีกครั้ง ... ดังนั้นจึงไม่มีการเรียกเก็บขยะและคุณเติมหน่วยความจำได้เร็วกว่าเด็กอ้วนกิน skittles
David Wilkins

37
@DavidWilkins: ... นี่คือ C ++, C ++ ไม่มีที่เก็บขยะ
Phoshi

32
หากคุณไม่คาดคิดว่ารหัสนี้จะรั่วไหลฉันคิดว่าคุณไม่ควรใช้ C ++ จนกว่าคุณจะเรียนรู้ได้ดีขึ้น
svick

1
@svick แต่มันก็ไม่เหมือนการพุ่งเป้าปาเป้าในที่มืด! ฉันมีความคิดว่าสิ่งนี้จะทำคำถามที่ต้องการงาน
Mukul Kumar

15
@svick เขาควรจะเรียนรู้วิธีการที่ดีกว่านี้อย่างไรถ้าเขาไม่ควรใช้ C ++
Kevin

16

brainfuck

+[>+]

คำอธิบาย:

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

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

beefเป็นล่ามตัวหนึ่งและมีให้ใน Ubuntu Software Center และการทำงานปัจจุบันของฉันบนเครื่องที่ไม่ได้ใช้เริ่มต้นเมื่อ 29 ชั่วโมงที่ผ่านมาและใช้ RAM ขนาด 1GB ในเวลานั้น นี่คือผลลัพธ์ของtop

PID  USER        PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND  
2978 sylwester   20   0 1030m 984m 2536 R 100,1 12,4   1750:52 beef

มันมีแคชขนาด 4GB และสลับขนาด 6GB ดังนั้นฉันเดาว่าฉันจะอัปเดตคำตอบนี้ด้วยวิธีที่ใช้ในอีกประมาณ 12 วัน

อัพเดท 03.24 17:11

PID  USER        PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND  
2978 sylwester   20   0 1868m 1,8g 2456 R  99,9 22,9   6008:18 beef    

อัพเดท 03.31 00:20

PID  USER        PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND  
2978 sylwester   20   0 2924m 2,8g 2052 R 100,0 36,1  15019:46 beef   

ดังนั้นมันจึงทำงานมา 10 วัน ดูเหมือนว่ามันจะทำงานอย่างน้อย 10 ครั้งก่อนที่สิ่งที่น่าสนใจจะเกิดขึ้น


ดีและสั้น
nrubin29

15

C และ POSIX

ที่นี่ฉันกำลังมองหาโซลูชั่นแบบพกพาอย่างมาก ปัญหาคือ pure C ดูเหมือนจะไม่มีวิธีบอกระบบปฏิบัติการว่าหน่วยความจำควรจะถูกจัดสรรหลังจากปิดโปรแกรม ดังนั้นฉันอนุญาตให้ตัวเองใช้ POSIX; ระบบปฏิบัติการส่วนใหญ่มีการอ้างถึงความเข้ากันได้ POSIX รวมถึง Windows, Linux และ MacOS X อย่างไรก็ตามฉันได้ทดสอบเฉพาะบน Ubuntu 12.04 32 บิตเท่านั้น มันไม่จำเป็นต้องมีสิทธิ์ superuser

วิธีนี้เป็นwhile(1){malloc(1);}วิธีแก้ปัญหาแบบดั้งเดิม อย่างไรก็ตามแทนที่จะเป็น malloc จะใช้ฟังก์ชันหน่วยความจำที่แชร์ POSIX เนื่องจากจะกำหนดตัวระบุหน่วยความจำที่ใช้ร่วมกันให้กับการจัดสรรแต่ละครั้งจึงยังคงเป็นไปได้ที่จะเข้าถึงหน่วยความจำได้เมื่อกระบวนการสิ้นสุดลง ดังนั้นเคอร์เนลจึงไม่สามารถเพิ่มหน่วยความจำได้

#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>

#define SHMSZ (2*1024*1024) /*Ubuntu rejects shared allocations larger than about 2MiB*/

main() {
  int shmid;
  key_t key = 0xF111; /* Lets use `Fill' as our first ID.*/
  char *shm;

  while(1) { /* Like malloc, but using shared memory */
    if ((shmid = shmget(key, SHMSZ, IPC_CREAT|0666)) < 0){return 1;}/*Get shared memory*/
    if ((shm = shmat(shmid, NULL, 0)) == (void *) -1) { return 1; } /*Attach it        */
    memset(shm,0,SHMSZ);                                            /*Fill it up       */
    key++                                                           /*On to the next ID*/
  }
}

คำตอบ C ที่ดีที่สุดและยอดเยี่ยมที่สุด IMO +1
syb0rg

1
ทำได้ดีนี่. วิธีแก้ปัญหาแรกที่ฉันพบคือ Andrew Medico แต่เป็นไปไม่ได้บน Linux และเมื่อฉันไม่ชอบการเขียนโปรแกรม Windows ฉันต้องการรั่วไหลผ่านหน่วยความจำที่ใช้ร่วมกัน แต่จำชื่อฟังก์ชัน POSIX ไม่ได้ ขอขอบคุณสำหรับการจดจำฉันของพวกเขา;) ทั้งหมดที่ฉันพบเป็นเพียงสิ่งที่เป็น mmap unmapped เมื่อมีการสิ้นสุดกระบวนการ ...
foobar

14

C #

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

using System;

class A
{
    public event Action Event;
}

class B
{
    public void Handler() { }
}

class Program
{
    static void Main()
    {
        A a = new A();

        while( true )
            a.Event += new B().Handler;
    }
}

คำอธิบาย : ภายในwhileลูปเราสร้างวัตถุใหม่ทำให้เฟรมเวิร์กจัดสรรหน่วยความจำเพิ่มเติม แต่เรายังป้องกันอินสแตนซ์ใหม่ของBการเผยแพร่เมื่อมันออกนอกขอบเขตโดยกำหนดวิธีอินสแตนซ์ให้กับเหตุการณ์ในคลาสอื่น ผลลัพธ์ที่ว่าอินสแตนซ์ใหม่ของBไม่สามารถเข้าถึงได้จากรหัสของเรา แต่ยังมีการอ้างอิงอยู่หมายความว่า GC จะไม่ปล่อยจนกว่าaจะออกนอกขอบเขต

เหตุการณ์สแตติกมีข้อผิดพลาดเหมือนกันเนื่องจากพวกเขาไม่เคยออกนอกขอบเขตพวกเขาจะทำความสะอาดเมื่อกระบวนการสิ้นสุดลงเท่านั้นเว้นแต่คุณจะยกเลิกการสมัครจากกิจกรรมก่อน จัดเก็บข้อมูลอ้างอิงของคุณทุกคนเสมอ!

using System;

class Program
{
    static event Action Event;

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

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

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

นี่คือตัวอย่างที่ใช้วัตถุและอาร์เรย์แบบคงที่

using System;
using System.Collections.Generic;

static class Leak
{
    private static List<decimal[]> Junk;

    static Leak()
    {
        Junk = new List<decimal[]>();
    }

    public static void Add( uint size )
    {
        decimal[] arr = new decimal[size];
        Junk.Add( arr );
    }
}

class Program
{
    static void Main()
    {
        while( true )
            Leak.Add( 1 );
    }
}

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


10

ทุบตี (ไม่มีสาธารณูปโภคภายนอก)

ไม่มีส้อมระเบิดที่นี่

คำเตือน:มันอาจฆ่าเปลือกของคุณ

แค่พยายามสร้างอาร์เรย์ของจำนวนเต็มเพื่ออ้างอิงเพราะฉันลืมไปว่ามีลักษณะเป็นจำนวนเต็มเท่าใด

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

ผลลัพธ์ใน:

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

2
+1 สำหรับ "เพราะฉันให้ลืมวิธีจำนวนเต็มมีลักษณะเหมือน" :)
เดวิดคอนราด

8

J (7)

คำเตือน:สิ่งนี้ทำให้ระบบของฉันค้างเมื่อฉันลองใช้ (Windows 8, J 8.01, ในเทอร์มินัล qt)

2#^:_[_
  • 2# เพิ่มความยาวของอาร์กิวเมนต์เป็นสองเท่าโดยการทำซ้ำแต่ละองค์ประกอบ
  • ^:_ ค้นหา fixpoint ของฟังก์ชันที่กำหนด (แต่ไม่มีหนึ่งฟังก์ชันจึงวนซ้ำไม่รู้จบ)
  • [_เรียกว่า_เป็นอาร์กิวเมนต์

8

Haskell (หมายเลขของ Graham)

ง่ายมากมันคำนวณจำนวนของเกรแฮม

ไม่เหมือนกับตัวอย่างอื่น ๆ ที่นี่มันจะไม่ทำงานตลอดไป ... มันจะใช้ cpu จำนวนมาก แต่ในทางทฤษฎีแล้วมันสามารถยุติได้ หากไม่ใช่เพื่อเก็บหมายเลข ...

จักรวาลอยู่ไกลขนาดเล็กเกินไปที่จะมีการแสดงดิจิตอลสามัญของจำนวนของเกรแฮมสมมติว่าแต่ละหลักตรงบริเวณหนึ่งปริมาณพลังค์

(ตามวิกิพีเดีย)

import Data.Sequence
import Data.Foldable

(↑) a 1 b = a ^ b
(↑) a _ 0 = 1
(↑) a i b = a ↑ (i-1) $ a ↑ i $ b-1

graham = last $ toList $ iterateN 64 (\i -> 3 ↑ i $ 3) 4
main = print graham

ดังนั้นแนวคิดก็คือหน่วยความจำจะถูกใช้งานอย่างมหาศาลInteger( อนุกรมเพิ่มขึ้น) อย่างมหาศาล(จำนวนเต็มของ Haskell มีขนาดตามอำเภอใจ)

ghciหากคุณต้องการที่จะทดสอบออกคุณอาจจะต้องเพิ่มขนาดของสแต็คหรือโหลดไว้ภายใน


2
จักรวาลใบ้ไม่สอดคล้องกับมาตรฐาน Haskell สำหรับจำนวนเต็ม ทำไมมันไม่รองรับขนาดที่กำหนดเอง?
PyRulez

6

แรงบันดาลใจจาก @comintern

แทนที่ / dev / null กำลังเข้าสู่โหมดลับ ๆ ล่อ ๆ ต้องใช้ส่วนหัวของเคอร์เนลโหมด superuser และคอมไพเลอร์ที่ใช้งานได้

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

มีความสุข.

Makefile:

MODULE := devnull
KVERS  ?= $(shell uname -r)
KDIR   ?= /lib/modules/$(KVERS)/build
KMAKE := make -C $(KDIR) M=$(PWD)

obj-m += $(MODULE).o

all:
    $(KMAKE) modules

install:
    $(KMAKE) modules_install

clean:
    $(KMAKE) clean

รหัสแหล่งที่มา:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/version.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/uaccess.h>

#define DEVICE_NAME "null"
#define MAJOR_NUMBER 0

MODULE_LICENSE("GPL");
MODULE_AUTHOR("nola <florian@n0la.org>");
MODULE_DESCRIPTION("/dev/null - memory leak style");
MODULE_VERSION("0.1");
MODULE_SUPPORTED_DEVICE("null");

static struct class *class_null;
static int major = 0;

static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
static loff_t device_llseek(struct file *, loff_t, int);

static struct file_operations fops = {
    .owner = THIS_MODULE,
    .llseek = &device_llseek,
    .read = &device_read,
    .write = &device_write,
    .open = &device_open,
    .release = &device_release
};

static int __init mod_init(void)
{
    struct device *dev_null;

    if ((major = register_chrdev(MAJOR_NUMBER, DEVICE_NAME, &fops)) < 0) {
        return major;
    }

    /* create /dev/null
     * We use udev to make the file.
     */
    class_null = class_create(THIS_MODULE, DEVICE_NAME);
    if (IS_ERR(class_null)) {
        unregister_chrdev(major, DEVICE_NAME);
        return -EIO;
    }

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
    dev_null = device_create(class_null, NULL, MKDEV(major, 0),
                             NULL, "%s", DEVICE_NAME
        );
#else
    dev_null = device_create(class_null, NULL, MKDEV(major, 0),
                             "%s", DEVICE_NAME
        );
#endif
    if (IS_ERR(dev_null)) {
        class_destroy(class_null);
        unregister_chrdev(major, DEVICE_NAME);
        return -EIO;
    }

    return 0;
}

static void __exit mod_exit(void)
{
    device_destroy(class_null, MKDEV(major, 0));
    class_unregister(class_null);
    class_destroy(class_null);
    unregister_chrdev(major, DEVICE_NAME);
}

static int device_open(struct inode *inode, struct file *file)
{
    file->f_pos = 0x00;

    try_module_get(THIS_MODULE);
    return 0;
}

static int device_release(struct inode *inode, struct file *file)
{
    /* decrement usage count: Not. Uncomment the line for less fun. */
    /* module_put(THIS_MODULE); */
    return 0;
}

static loff_t device_llseek(struct file *filep, loff_t offs, int mode)
{
    loff_t newpos;

    switch (mode) {
    case 2:
    case 0:
        newpos = offs;
        break;

    case 1:
        newpos = filep->f_pos + offs;
        break;

    default:
        return -EINVAL;
    }

    if (newpos < 0) {
        return -EINVAL;
    }

    filep->f_pos = newpos;

    return newpos;
}

static ssize_t device_read(struct file *filep, char *dst, size_t len,
                           loff_t *off)
{
    char *buf = NULL;

    if (dst == NULL || len == 0) {
        return -EINVAL;
    }

    buf = kmalloc(sizeof(char) * len, GFP_KERNEL);
    if (buf == NULL) {
        return -EINVAL;
    }

    /* Do how a /dev/null does.
     */
    memset(dst, 0, len);

    *off += len;
    return len;
}

static ssize_t device_write(struct file *filep, const char *src, size_t len,
                            loff_t *off)
{
    char *buf = NULL;

    buf = kmalloc(sizeof(char) * len, GFP_KERNEL);
    if (buf == NULL) {
        return -EINVAL;
    }

    *off += len;
    return len;
}

module_init(mod_init);
module_exit(mod_exit);

คำเตือนอาจทำให้คุณต้องรีบู๊ต!

หากต้องการลบ:

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

6

ทับทิม

ทุกคนรู้ว่าผลรวมนั้น (1 / n ^ 2) = pi ^ 2/6

ดังนั้นฉันสามารถกำหนดฟังก์ชันการประมาณ:

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

p pi_approx.(100_000)

แน่นอนว่า (1..infinity) จะแสดงผลเป็นป่า

อย่างไรก็ตามโปรดสังเกตว่าการใช้ขี้เกียจจะทำให้งานนี้;)

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

p pi_approx.(100_000)
#=> 3.141583104326456

5

C - 28 25 อักขระ (โปรแกรมเต็มรูปแบบ)

อย่าเรียกใช้งานไฟล์นั้นมิฉะนั้นระบบของคุณจะหยุดทำงานอย่างรวดเร็ว!

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

การเรียกใช้ malloc จะสำรองหน่วยความจำ 9 ไบต์และร้องขอหน้าหน่วยความจำใหม่จากระบบปฏิบัติการเป็นประจำ หน่วยความจำที่จัดสรรโดย malloc ถูก leaked ทันทีเนื่องจากไม่มีการเก็บตัวชี้ไปยังที่อยู่ที่ส่งคืน เมื่อระบบมีหน่วยความจำไม่เพียงพอ (RAM และพื้นที่สว็อป) หรือถึงขีด จำกัด หน่วยความจำสำหรับกระบวนการโปรแกรมจะแยกจาก while-loop และสิ้นสุดลง


2
ไม่นานระบบที่ทันสมัยอย่างมีเหตุผลควรมีนักฆ่า OOMที่เตะเข้าและฆ่ากระบวนการ อย่างน้อย Ubuntu 12.04 ทำ
Digital Trauma

1
ดีฉันชนอูบุนตูของฉัน 13.10 ในขณะที่พยายามรหัสนี้ ...
Mathieu Rodic

@DigitalTrauma เช่น FreeBSD มี OOMK หรือไม่
Ruslan

1
main(){while(malloc(9));}บันทึกอีก 3 ตัวละครและเติมความทรงจำของฉันทันที
gmatht

@ gmatht: ขอบคุณสำหรับคำแนะนำ! ฉันแก้ไขคำตอบ ... แม้ว่าฉันชอบความคิดในการเพิ่มขนาดของบล็อกในทุกลูป
Mathieu Rodic

4

VBScript

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

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

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


เอ่อจริงเหรอ? VBScript ไม่เพียง แต่ใช้ VB.NET ภายใต้ประทุน? การอ้างอิงแบบวงกลมไม่ใช่ปัญหาสำหรับนักสะสมขยะยกเว้นสำหรับการใช้งานการนับการอ้างอิงอย่างง่ายและการสิ้นสุดของโปรแกรมควรส่งผลให้ปล่อยฮีปทั้งหมดใช่หรือไม่
David Conrad

@DavidConrad คุณจะคิดอย่างนั้น แต่ฉันต้องรีสตาร์ทเครื่องทุกครั้งที่ฉันตรวจสอบและเรียกใช้สคริปต์ประเภทนี้
AutomatedChaos

1
VBScript ถือกำเนิด VB.Net อย่างมีนัยสำคัญ - มันไม่ได้เป็นรุ่นบรรทัดคำสั่งของ VB.Net; มันเป็นเซตย่อยที่ถูกตีความของ Visual Basic ดั้งเดิม
Chris J

ขอบคุณคุณทั้งคู่ ฉันไม่ทราบว่าความสัมพันธ์ระหว่าง VBScript กับ VB.NET นั้นเป็นอย่างไร
David Conrad

4

ใช่ & tmpfs

ทำไมต้องเขียนโปรแกรมใหม่เมื่อใช้งานฟรีกับ Ubuntu

yes > /run/user/$UID/large_file_on_my_ramdisk

อย่างที่คุณอาจจะรู้หรือเคยเดามาก่อนว่า Ubuntu ติดตั้ง / รัน / ผู้ใช้ / โดยค่าเริ่มต้นเป็น tmpfs ซึ่งเป็นดิสก์ RAMชนิดหนึ่ง

คุณไม่ต้องปิดมันด้วยซ้ำ มันจะปิดตัวเองอย่างสุภาพทำให้เหลือหน่วยความจำอันดีไว้ ฉันเข้าใจว่าyesเป็นโปรแกรมแบบ single-threaded process ซึ่งไม่ได้เรียกสิ่งอื่นใด (การเขียนไปยังดิสก์ RAM ที่มีอยู่นั้นสามารถพกพาไปยังภาษาที่คุณเลือกได้เล็กน้อย)

มีข้อผิดพลาดเล็กน้อย: Ubuntu จำกัด ผู้ใช้ที่เขียนได้ tmpfs / run / 1,000 ถึง 100 MB โดยค่าเริ่มต้นดังนั้นคุณสมบัติ swap death อาจไม่ได้รับการสนับสนุนบนเครื่องของคุณ อย่างไรก็ตามฉันจัดการเพื่อแก้ไขปัญหานี้ในเครื่องของฉันด้วยวิธีแก้ปัญหาด่วนดังต่อไปนี้:

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

ฉันไม่มี/run/userไดเรกทอรีเลย คุณใช้ Ubuntu รุ่นใดและคุณติดตั้งรุ่นใด
Ruslan

Ubuntu Trusty Tahr (14.04) ไม่จำเป็นต้องติดตั้งแบบพิเศษ
gmatht

เพื่อค้นหาว่าคุณมีtmpfsfilesystems df -t tmpfsติดตั้งคุณสามารถแสดงรายการพวกเขาด้วย ระบบ Ubuntu ของฉันมีขนาดใหญ่น่ารัก/run/shmพร้อมใช้งาน ...
Toby Speight

4

ทุบตี

คำเตือน: รหัสต่อไปนี้จะทำให้คอมพิวเตอร์ของคุณไม่สามารถบูตได้

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

คำเตือน: รหัสก่อนหน้านี้จะทำให้คอมพิวเตอร์ของคุณไม่สามารถบูตได้

แทนที่ / dev / sda ด้วย boot drive ของคุณ นี่เขียน E8 FD FF ไปยังการเริ่มต้นเซกเตอร์สำหรับเริ่มระบบของคุณ เมื่อทำการบูท BIOS จะอ่านเซกเตอร์สำหรับเริ่มระบบของคุณลงในหน่วยความจำและดำเนินการ opcodes เหล่านั้นเทียบเท่ากับชุดประกอบนี้:

label:
  call label

นี่เป็นการเรียกซ้ำแบบไม่สิ้นสุดซึ่งจะทำให้เกิดการล้นสแต็กในที่สุด


ในตัวอย่างชุดประกอบของคุณคุณสามารถบันทึกอักขระ (สมมติว่าจำเป็นต้องใช้ชื่อ "ป้ายกำกับ") โดยใช้jmpแทนcall
SirPython

call ปล่อยให้แอดเดรสอยู่บนสแต็กสำหรับ ret กระโดดจะไม่ทำให้เกิดการล้นสแต็ค
Jerry Jeremiah

3

Haskell

main=print $ sum [0..]

นี่จะพยายามเพิ่มจำนวนการนับ Haskell ทำการประเมินผลรวมบางส่วนมันก็กลายเป็นคำสั่งที่ไม่มีที่สิ้นสุด หากคุณเรียกใช้คอมไพเลอร์ด้วยแฟล็กการปรับให้เหมาะสมอาจไม่ทำงาน


3

ทุบตี

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

สคริปต์นี้ดำเนินการเพิ่มประสิทธิภาพสองอย่าง: (1) การติดตั้ง tmp เป็น tmpfs (ดิสก์ RAM ชนิดหนึ่ง) เพื่อให้ / tmp เร็วขึ้นและ (2) การสร้าง swapfile เพื่อเพิ่มหน่วยความจำ แต่ละสิ่งเหล่านี้มีเหตุผลด้วยตัวเอง แต่ถ้าผู้ใช้เลินเล่อทำทั้งสองอย่างมันจะตั้งค่าวงจรของการแลกเปลี่ยน: เมื่อระบบปฏิบัติการพยายามสลับหน้าออกมันจะเขียนไปยัง tmpfs; สิ่งนี้ทำให้ tmpfs ใช้หน่วยความจำเพิ่มขึ้น สิ่งนี้จะเพิ่มแรงกดดันหน่วยความจำทำให้มีการสลับหน้าเพิ่มขึ้น ซึ่งอาจใช้เวลาไม่กี่นาทีใน VM topของฉันเวลามากมายเพื่อให้คุณชมระบบขุดตัวเองลงไปในหลุมโดยใช้

การปิดโปรแกรมสร้างความแตกต่างเพียงเล็กน้อยเนื่องจากโปรแกรมจัดสรรหน่วยความจำแทบจะไม่ แน่นอนว่ามันไม่สำคัญที่จะเพิ่มหน่วยความจำเนื่องจากคุณไม่สามารถเพิ่มหน่วยความจำได้โดยการยกเลิกการถอด tmpfs ก่อนที่คุณจะswapoffเปลี่ยนไฟล์และมันยากที่จะทำจนกว่าคุณจะมีหน่วยความจำว่าง

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

sudo mount -t tmpfs -o size=9999G tmpfs /tmp # Use tmpfs to make /tmp faster
truncate -s 4096G /tmp/swap                  # Now make a giant swap file to free up memory 
sudo losetup /dev/loop4 /tmp/swap            # Use a loopback so we can mount the sparse file
sudo mkswap /dev/loop4
sudo swapon /dev/loop4
#The following line would cause a quick swap death, but isn't needed.
#dd if=/dev/zero of=/tmp/zero bs=1          # Zero the tmp dir so the VM can free more memory

2

Perl

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

ใช้การอ้างอิงแบบวงกลม จำนวนการอ้างอิงของตัวแปรจะไม่ถึง 0 และการอ้างอิงจะไม่ถูกรวบรวมขยะ

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


2

PHP (ลินุกซ์เท่านั้น):

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

แต่นี่เป็นข้อพิสูจน์แนวคิดของฉัน:

ignore_user_abort(true);
ini_set('memory_limit',-1);
ini_set('max_execution_time',0);
/*
    sets php to ignore if the script was canceled in the browser
    (like clicking cancel or closing the browser)
    and takes away the memory limit,
    as well as the maximum execution time.
*/

function dont_let_it_stop(){shell_exec('php '.__FILE__.' &');}
//this function calls the file itself.

register_shutdown_function('dont_let_it_stop');
//this function will register the function declared above to be used when the script is being terminated

function get_info($f='current')
{
    return str_replace(' kB','',end(explode(':',trim($f(explode(PHP_EOL,file_get_contents('/proc/meminfo')))))))*1024
}
/*
    this function fetches the infos
    'current' fetches the max memory
    'next' fetches the actual used memory
*/

$max=get_info();//maximum memory
$current=get_info('next');//current memory

$imgs=array(imagecreatetruecolor(1e4,1e4));
$color=imagecolorallocatealpha($imgs[$i=0],128,128,128,126);
imagefill($imgs[$i],0,0,$color);
/*
    this creates an array and inserts one image (10000x10000 pixels),
    filling it then with a solid transparent color
*/

$total-=get_info('next');//calculates the space an image takes

while($max-get_info('next')>$total*2)//while the free memory is higher than the memory of 2 images, fill the array
{
    $imgs[$i++]=imagecreatetruecolor(1e4,1e4);
    $color=imagecolorallocatealpha($imgs[$i-1],128,128,128,126);
    imagefill($imgs[$i-1],0,0,$color);
}

//this is just to keep the images in memory, so the script doesn't end
while(1)sleep(60);

วิธีนี้จะเติมหน่วยความจำด้วยภาพ RGBA ขนาดใหญ่ (10,000x10000 พิกเซล)

วิธีเดียวที่จะปิดลูกน้อยนี้ได้คือการปิดเครื่อง

รหัสมีการแสดงความคิดเห็นทั้งหมด

การปรับปรุงข้อสงสัยข้อผิดพลาดหรืออะไรก็ตามใช้ช่องแสดงความคิดเห็นด้านล่าง


ทุกคนที่สามารถใช้งาน linux mind ทดสอบได้หรือไม่ ขอบคุณ :)
George

ฉันมีลินุกซ์ฉันไม่แน่ใจว่ามันจะทำงานได้อย่างไร ฉันให้พิมพ์หน้าจอสำหรับคำตอบที่ 1 แต่นั่นเป็นลูกสุนัขลินุกซ์รุ่นเก่าจริง ๆ Ubuntu ช้าเกินไปที่จะเรียกใช้ php บางทีฉันอาจทดสอบกับ Android ในภายหลัง
Ismael Miguel

1
มันล้มเหลวในจุดที่ไม่ได้เรียกโปรแกรมอื่น
Einacio

ไม่ได้เรียกโปรแกรมอื่น: กำลังเรียกโปรแกรมเดียวกันที่เริ่มต้นไฟล์สำหรับไฟล์เดียวกัน
Ismael Miguel

2

Python - 56

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

สร้างคลาสกำหนดวิธีการสำหรับการตั้งค่าคุณลักษณะตั้งค่าแอตทริบิวต์ในนั้นและสร้างอินสแตนซ์เริ่มต้นซึ่งจะพยายามตั้งค่าคุณลักษณะของ

ฟังก์ชั่นเรียกซ้ำง่าย ๆ ( def f(x):f(x)) ดูเหมือนจะไร้ความรู้สึกดังนั้นฉันตัดสินใจว่าจะไม่เรียกฟังก์ชั่นจริง ๆ

การจัดการหน่วยความจำอาจเป็นไปตามความลึกของการเรียกซ้ำ

หากนี่คือการทิ้งระเบิดโปรดบอกฉัน


4
RuntimeError: maximum recursion depth exceeded while calling a Python objectนี้ไม่ก่อให้เกิดความอ่อนเพลียหน่วยความจำเพียง: แม้แต่การตั้งค่าขีด จำกัด การเรียกซ้ำสูงสุดโดยsys.setrecursionlimitแทบจะไม่ใช้หน่วยความจำใด ๆ ก่อนที่จะเกิดปัญหากับข้อผิดพลาดการแบ่งกลุ่ม
Bakuriu

@Bakuriu อย่างที่ฉันพูดมันขึ้นอยู่กับการนำไปใช้จริง ๆ (มีการใช้งานของ Python ที่แปลงเป็น C (++) และคอมไพล์เช่น Shedskin, Nuitka)
cjfaure

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

2

Perl

มันง่าย แต่ฉันรู้สึกเหมือนเล่นกอล์ฟ

{$x=[$x];redo}

หลังจากที่ทั้งสองทำซ้ำมีการอ้างอิงไปยังอาร์เรย์ที่มีการอ้างอิงไปยังอาร์เรย์ที่มี$xundef

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


2

ECMAScript 6:

z=z=>{while(1)z()};_=i=>(i+=1,i-=1,i++,i--,--i,++i,i<<=2,i>>=2,i+=0|Math.round(1+Math.random())&1|0,z(x=>setInterval(x=>z(x=>new Worker('data:text/javascript,'+_.toSource()),5))));setInterval(x=>z(x=>_(...Array(9e3).map((x,z)=>z*3/2*2/4*4e2>>2<<2))),5)

Ungolfed:

function forever(code) {
    // Loop forever
    var counter = 0;

    while (counter++ < 10) setInterval(code, 5);
};

function main(counter) {
    // Do some work.
    counter += 1; counter -= 1;

    counter++; counter--;
    --counter; ++counter;

    counter <<= 2;
    counter >>= 2;

    counter += 0 | Math.round(1 + Math.random()) & 1 | 0;

    forever(() => {
        setInterval(() => {
            forever(() => new Worker('data:text/javascript,' + main.toString()));
        }, 5);
    });
};

setInterval(() => {
    forever(() => {
        main(...Array(9e3).map((currentValue, index) => index * 3 / 2 * 2 / 4 * 4e2 >> 2 << 2));
    });
}, 5);

หมายเหตุ: มันใช้setTimeoutซึ่งถูกกำหนดให้เป็นส่วนหนึ่งของตัวจับเวลา - HTML ที่นั่งเล่นมาตรฐาน

ลองใช้กับ Mozilla Firefox (คุณสามารถวางไว้ในคอนโซลนักพัฒนาซอฟต์แวร์) Firefox ช่วยให้กินหน่วยความจำมากขึ้นและการใช้งาน100%ของ CPU บนเครื่อง single-core (บนเครื่อง 4-core เช่นเหมืองจะใช้25%ของ CPU) นอกจากนี้ยังมีประโยชน์เพิ่มเติมที่คุณไม่สามารถหยุดมันได้ หากคุณสามารถเปิดตัวจัดการงานคุณสามารถฆ่า Firefox ได้


1
มันใช้หลัก 100% บนโปรเซสเซอร์ Quadcore ของคุณผลลัพธ์ 25% ของการใช้ CPU
IvánPérez

@Electrosa ใช่คุณถูกต้องอย่างแน่นอน ฉันอัพเดตคำตอบแล้ว
แปรงสีฟัน

นี่ไม่ใช่คำถามเกี่ยวกับรหัสกอล์ฟโปรดพยายามทำให้โค้ดของคุณอ่านได้
Paŭlo Ebermann

@ PaŭloEbermannตกลง ฉันโพสต์เวอร์ชันที่ไม่ดี
แปรงสีฟัน

1

ทุบตี

สร้างไฟล์เปล่าtest
แทนที่/dev/null/ด้วยไฟล์ข้อความนี้

$ sudo mv test /dev/null

สิ่งนี้ทำงานในลักษณะเดียวกันกับคำตอบของ @ Comintern ผลลัพธ์ทั้งหมดที่/dev/nullจะถูกผนวกเข้ากับไฟล์ข้อความนี้ซึ่งเมื่อเวลาผ่านไปจะมีขนาดใหญ่และทำให้ระบบพัง


1
ไฟล์ขนาดใหญ่จะไม่ผิดพลาดของระบบ และสมมติว่าขนาดดิสก์เฉลี่ย 500gb มันจะใช้เวลานานสำหรับไฟล์ที่จะได้เข้าใกล้เพื่อเติมดิสก์
w4etwetewtwet

1
บนระบบที่/devเป็น a devtmpfsมันอาจเติมและขัดขวางระบบ ฉันเดาว่านั่นเป็นเจตนาของคำตอบนี้
Toby Speight

1

Bash: 7 ตัวอักษร

นี่ควรเป็นวิธีทุบตีที่ง่ายที่สุด ไม่มีส้อมไม่มีการโกง

x=`yes`

คุณไม่ควรเรียกใช้สิ่งนี้ในฐานะรูท


หมายเหตุเพิ่มเติม: แม้ว่าคุณจะยุติสิ่งนี้ด้วย ctrl-c กึ่งกลางและจากนั้นunsetตัวแปรหน่วยความจำจะยังคงถูกจัดสรรจนกว่าเชลล์จะถูกฆ่า คุณสามารถดูการสังหารtopได้
Riot

การทดสอบของฉันเองด้วย bash 4.2.45 (1) แสดงว่าunset xเพิ่มหน่วยความจำ pdksh ยังเพิ่มหน่วยความจำด้วย แต่ ksh93 ล้มเหลวในการทำให้เป็นอิสระและexitใน ksh93 ดัมพ์คอร์
kernigh

สำหรับฉัน (ทุบตี 4.3.11 (1)) หน่วยความจำถิ่นที่อยู่จะแสดงที่ด้านบนสำหรับเปลือกหอยหลักปีนขึ้นไปเรื่อย ๆ จนกว่าyesจะถูกฆ่าตาย ณ จุดที่มันเพิ่งจะอยู่ที่นั่นโดยunsetไม่มีผลใด ๆ แต่นี่เป็นระบบหน่วยความจำขนาดใหญ่และการมีตัวแปรที่มีหลายกิกะไบต์ดูเหมือนว่าจะไม่เกิดปัญหา (จนกระทั่งในที่สุดมันก็ตัดสินใจฆ่าเชลล์)
จลาจล

0

C

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

เอาหน้าหน่วยความจำหลังจากหน้าและในที่สุดก็ไม่มีหน่วยความจำ


หน้าเพจขนาด 4 KB เป็นสากลเพียงใด
Peter Mortensen

@Peter 4K มักจะมีขนาด แต่ฉันไม่สามารถบอกได้ว่ามันเป็นสากลจริง ๆ แต่ขนาดหน้าไม่มีความสัมพันธ์กับคำถามที่กำหนด
ST3

1
@ ST3: คุณควรทำให้หน้าหน่วยความจำสกปรก ระบบปฏิบัติการที่ทันสมัยส่วนใหญ่ใช้หน่วยความจำเสมือนและบันทึกในตารางหน่วยความจำเสมือนเมื่อคุณจัดสรรหน่วยความจำ การเขียนไบต์เดียวไปยังหน้าหน่วยความจำจะบังคับให้ระบบปฏิบัติการแมปหน้าหน่วยความจำเสมือนกับหน่วยความจำกายภาพ
foobar

ดูcodegolf.stackexchange.com/questions/24485/...
Mathieu Rodic

0

ทับทิม

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

มันเพิ่มการอ้างอิงตัวเอง (เรียกซ้ำ!) ต่อท้ายอย่างไม่มีที่สิ้นสุด

พบข้อมูลเกี่ยวกับอัญมณีน้อยนี้เมื่อมีคนยากจน Sandbox ทับทิมของฉันกับมัน : D

การสาธิตลักษณะวนซ้ำของมัน:

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

0

C ++ 79

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

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

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

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

ฉันแก้ไขรายการที่จะรวมการโทรจากสายหลัก


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