Tạo rò rỉ bộ nhớ, không có bất kỳ quả bom ngã ba nào [đóng]


54

Nhiệm vụ của bạn là tạo ra một rò rỉ bộ nhớ . Đây là một chương trình sử dụng vô số bộ nhớ, cho đến khi máy tính hết và phải thực hiện một số thao tác hoán đổi để tự cứu mình khỏi bị hết. Cách duy nhất mà bộ nhớ có thể được giải phóng là bằng cách giết chương trình trong trình quản lý tác vụ hoặc sử dụng lệnh giết dòng lệnh như taskkill /im yourprogram /f(trong Windows) hoặc thậm chí khởi động lại máy tính. Chỉ đóng ứng dụng sẽ không ngăn ứng dụng tiếp tục hog bộ nhớ.

Quy tắc:

  1. Bom ngã ba của bất kỳ loại nào đều bị cấm. Điều đó có nghĩa là dòng Bash khét tiếng :(){ :|:&};:bị cấm!

  2. Ứng dụng phải là một luồng duy nhất. Điều này ngụ ý quy tắc bom ngã ba.

  3. Chương trình không được chạy các chương trình khác. Điều này có nghĩa là bạn không thể làm một cái gì đó như run(memoryfiller.exe). Ngoại lệ duy nhất này là các chương trình đi kèm với hệ điều hành hoặc ngôn ngữ của bạn, không được thiết kế chủ yếu để tiêu thụ bộ nhớ (tức là chúng có mục đích khác). Điều này có nghĩa là những thứ như catln -sđược cho phép.

  4. Bạn có thể chiếm nhiều bộ nhớ như bạn muốn. Càng nhiều càng tốt.

  5. Mã phải được giải thích đầy đủ.

Chúc may mắn. Đây là một cuộc thi phổ biến vì vậy mã có nhiều phiếu bầu nhất sau 10 ngày kể từ ngày hỏi sẽ thắng!


8
"Đóng nó vẫn sẽ khiến bộ nhớ hog" - nếu một chương trình là một trình thực thi shell (giống như hầu hết các phiên bản windows của trình thông dịch ngôn ngữ kịch bản), việc đóng cửa sổ của nó sẽ giết chương trình.
mniip

54
Đây không phải là chỉ while(1)malloc(999);?
Doorknob

10
Tôi không chắc chắn nếu "Đóng nó vẫn sẽ khiến bộ nhớ hog" tương thích với "Ứng dụng phải là một luồng duy nhất." Nếu không có luồng nào có bộ nhớ, hệ điều hành có thể lấy lại, phải không?
aebabis

51
Chỉ cần chạy firefox 26 với một vài tab mở flash chạy trong nửa giờ. Nó sẽ đưa máy tính của bạn đến đầu gối của nó.
Braden hay nhất

1
@mniip. Đó là toàn bộ điểm của thử thách. Để thực hiện một thử thách khó khăn. Và tay nắm cửa. Tôi muốn một cái gì đó khác biệt! ;)
George

Câu trả lời:


78

các cửa sổ

API Win32 cho phép bạn phân bổ bộ nhớ trong các quy trình khác và sau đó đọc / ghi bộ nhớ đó từ xa. Chương trình này chỉ có một luồng, nó sử dụng để liệt kê từng tiến trình đang chạy trên hệ thống, và sau đó liên tục phân bổ bộ đệm 1MB trong mỗi quy trình cho đến khi việc phân bổ thất bại. Khi nó kết thúc với một quá trình, nó chuyển sang bước tiếp theo. Việc phân bổ không được giải phóng khi chương trình gọi kết thúc - chỉ khi / nếu mỗi quá trình đích kết thúc. Điều này sẽ treo một máy ảo Windows 7 2GB trong khoảng 10 giây. Nó không yêu cầu chạy như quản trị viên.

Để biên dịch: 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 là xấu xa.
tomsmeding

4
Tôi cần phải đóng cửa tối nay. Ill cho điều này đi;)
George

1
"(chạy như một người dùng bình thường, không sử dụng đặc quyền quản trị viên" - không chắc chắn về điều này, bạn cần SeDebugPriv đặc quyền mà theo mặc định không có trong mã thông báo của người dùng thông thường
rkosegi

@rkosegi Cảm ơn, đã sửa.
Andrew Medico

14
+1 Điều này xứng đáng nhận được nhiều sự ủng hộ vì cho đến nay nó là câu trả lời duy nhất đáp ứng được Đóng ban đầu, nó vẫn sẽ khiến nó trở thành yêu cầu bộ nhớ . Giải pháp rất sáng tạo :-)
Daniel

72

Java

import java.util.concurrent.atomic.AtomicInteger;

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

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

Giải trình

Bạn có thể cho rằng vì không có tài liệu tham khảo nào trong mã (ngoài ra count, bạn có thể bỏ qua một cách an toàn), nên nó không thể bị rò rỉ. Tuy nhiên, bộ hoàn thiện tạo ra hai Hydras mới và trong khi nó không chứa tài liệu tham khảo cho những cái này, chúng sẽ tồn tại cho đến khi hoàn thành. Điều này có nghĩa là chương trình chỉ rò rỉ bộ nhớ trong quá trình thu gom rác - do đó các cuộc gọi đến System.gc()System.runFinalization().


7
@TimS. chúa của bạn bây giờ ở đâu?!?
Cruncher

Được System.gc()System.runFinalization()cần thiết? Đó là đôi khi gc sẽ chạy ngẫu nhiên, hoặc bạn phải lấp đầy bộ nhớ, hoặc gọi gc?
Cruncher

4
Trong một chương trình điển hình, System.gc()System.runFinalization()sẽ không cần thiết. Thu gom rác sẽ xảy ra một cách tự nhiên do áp lực bộ nhớ. Tuy nhiên, trong ứng dụng này không có áp lực bộ nhớ cho đến khi bộ sưu tập rác bắt đầu chạy. Tôi đã nghĩ về việc giới thiệu một cách giả tạo một số (ví dụ, bằng cách di chuyển new Hydra()bên trong vòng lặp), nhưng hình dung điều này còn tệ hơn.
James_pic

1
Vâng, tôi đã không chú ý nhiều đến việc "Đóng nó vẫn sẽ khiến nó bị mất trí nhớ", vì nó có vẻ không có ý nghĩa (ngoài các bản hack hệ điều hành gọn gàng như @ German_guy's). Java luôn tạo ra một luồng hoàn thiện, vì vậy có lẽ không có cách nào để ứng dụng Java tuân theo quy tắc # 2.
James_pic

1
Trên các hệ thống Unix, bạn không thể chặn SIGKILL (tín hiệu 9), do đó bạn không thể khiến chương trình của mình không thể bị chặn (tốt, ngoại trừ nếu bạn quản lý để đưa nó vào trạng thái chờ đợi không bị gián đoạn ... vì vậy có thể giết chết máy chủ NFS có tệp của bạn truy cập có thể hoạt động ;-))
celtschk

37

C

Sử dụng ngôn ngữ lập trình C và được thử nghiệm với nhân Linux 2.6.32-49-generic và libc-2.11.1.so.

Cách duy nhất mà bộ nhớ có thể được giải phóng là bằng cách giết chương trình trong trình quản lý tác vụ hoặc sử dụng taskkill / im yourprogram / f hoặc thậm chí khởi động lại PC.

Điều này đạt được bằng cách chặn bất kỳ tín hiệu nào ngoại trừ SIGKILL và SIGSTOP.

Đóng nó vẫn nên làm cho nó hog bộ nhớ.

Điều này thực sự làm tôi bối rối ... Giết hoặc đóng cả hai đều dẫn đến việc chấm dứt quá trình, cho phép hệ điều hành lấy lại bất kỳ bộ nhớ nào được phân bổ bởi quy trình. Nhưng sau đó tôi đã nghĩ rằng bằng cách đóng nó, bạn có thể có nghĩa là đóng thiết bị đầu cuối hoặc bất kỳ quá trình cha mẹ nào khác thực hiện quá trình rò rỉ bộ nhớ. Nếu tôi hiểu đúng, thì tôi đã giải quyết vấn đề này bằng cách chặn bất kỳ tín hiệu nào, điều này biến quá trình thành một daemon khi quá trình cha mẹ bị chấm dứt. Bằng cách đó, bạn có thể đóng thiết bị đầu cuối mà quá trình đang chạy và nó sẽ tiếp tục chạy và tiến hành rò rỉ bộ nhớ.

Bom ngã ba của bất kỳ loại nào đều bị cấm. Điều đó có nghĩa là bash khét tiếng: () {: |: &};: bị cấm!

Quá trình không ngã ba.

Các ứng dụng phải được phân luồng duy nhất. Điều này ngụ ý quy tắc bom ngã ba

Không có chủ đề mới được sinh ra.

Chương trình không được chạy chương trình khác. Điều này có nghĩa là bạn không thể làm gì đó như chạy (memoryfiller.exe)

Không có quá trình mới được sinh ra.

Bạn có thể chiếm nhiều bộ nhớ như bạn muốn. Càng nhiều càng tốt.

Nhiều như hệ điều hành có thể cung cấp.

Mã phải được giải thích đầy đủ.

Đã thêm ý kiến ​​vào nguồn.

Và cuối cùng đây là mã:

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

Đối với bất kỳ ai quan tâm đến những gì sẽ xảy ra nếu bạn tiếp tục chạy chương trình này: Trên hệ thống thử nghiệm của tôi với RAM 2 GB và dung lượng trao đổi 4GB, mất khoảng 10 phút để lấp đầy RAM và trao đổi. Kẻ giết người OOM bắt đầu công việc của nó và ba phút sau đó, tất cả các quy trình đã bị giết. Ngay cả chuột, bàn phím và màn hình đã bị hệ thống bỏ. /var/log/kern.log cho thấy không có thông tin hữu ích, ngoại trừ các quy trình đã bị giết.


Tôi đã chỉnh sửa nguồn để làm cho kẻ giết người oom bỏ qua quá trình và giết các quy trình vô tội để giải phóng bộ nhớ thay thế.
foobar

5
Đối với bất kỳ ai quan tâm đến những gì sẽ xảy ra nếu bạn tiếp tục chạy chương trình này: Trên hệ thống thử nghiệm của tôi với RAM 2 GB và dung lượng trao đổi 4GB, mất khoảng 10 phút để lấp đầy RAM và trao đổi. Kẻ giết người OOM bắt đầu công việc của nó và ba phút sau đó, tất cả các quy trình đã bị giết. Ngay cả chuột, bàn phím và màn hình đã bị hệ thống bỏ. /var/log/kern.log cho thấy không có thông tin hữu ích, ngoại trừ các quy trình đã bị giết.
foobar

Haha, thật tuyệt vời Bạn nên chỉnh sửa mô tả đó vào câu trả lời của bạn. +1
Doorknob

1
Tôi đã không downvote, nhưng thật tuyệt nếu mã có thể được định dạng để không cần cuộn ngang để đọc các bình luận.
Paŭlo Ebermann

2
+1 cho 1) khiến các quy trình xử lý các thiết bị đầu vào / đầu ra bị giết và 2) tạo ra một chương trình khó theo dõi từ nhật ký. Đây là cấp độ ria mép của ác quỷ.
Kevin - Tái lập Monica

29

Bash tinh khiết

Không phải là một quả bom ngã ba, tôi hứa:

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

Nó trông rất giống một quả bom ngã ba, và sử dụng một kỹ thuật đệ quy tương tự, nhưng không có dĩa. Tất nhiên điều này sẽ chạy shell của bạn ra khỏi bộ nhớ, vì vậy bạn nên bắt đầu một shell mới trước khi dán lệnh này.

  • Xác định hàm gọi là :
  • Hàm chỉ đơn giản gọi đệ quy chính nó với $@(danh sách arg) nhân đôi
  • Sau khi định nghĩa hàm, :hàm được gọi với một đối số ban đầu:

Đầu ra:

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

Trong lần chỉnh sửa trước câu trả lời này tôi đã làm a=$(yes), nhưng tôi nhận thấy quy tắc "Chương trình không được chạy chương trình khác", vì vậy tôi cần sử dụng thuần túy bashthay vì không gọi bất kỳ coreutils hay bất cứ điều gì khác.


Đây là một số khác:

VUI LÒNG KHÔNG CHẠY NÀY TRÊN MÁY SẢN XUẤT

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

Một lần nữa, đây không phải là một quả bom ngã ba - mọi thứ được chạy từ trong một luồng. Điều này dường như khá thuận tiện để đưa Ubuntu VM của tôi đến đầu gối của nó, với rất ít chỗ để phục hồi, ngoài việc khởi động lại.

Như trong bom ngã ba cổ điển, một hàm đệ quy :()được xác định. Tuy nhiên, nó không bỏ cuộc gọi đến chính nó. Thay vào đó, nó tự gọi mình bằng một đối số, chính nó được gọi trong một sự thay thế quá trình . Bởi vì quá trình thay thế hoạt động bằng cách mở một bộ mô tả tệp /dev/fd/n, điều này không chỉ ngốn bộ nhớ quá trình (bash), mà còn ăn một số bộ nhớ kernel. Trên máy Ubuntu của tôi, điều này có tác dụng làm cho trình quản lý cửa sổ không thể hoạt động sau vài giây, sau đó không lâu sau khi kết thúc với màn hình này:

nhập mô tả hình ảnh ở đây

Nhấp vào OKsau đó cho màn hình này:

nhập mô tả hình ảnh ở đây

Không có tùy chọn nào trong số này có vẻ giúp ích nhiều - tại thời điểm này, khởi động lại dường như là lựa chọn tốt duy nhất.


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

2
"Cách duy nhất mà bộ nhớ có thể được giải phóng là bằng cách giết chương trình trong trình quản lý tác vụ hoặc sử dụng taskkill / im yourprogram / f hoặc thậm chí khởi động lại PC. Đóng nó vẫn khiến bộ nhớ hog." >> Bash có thể được chấm dứt bằng SIGTERM, do đó, giết nó là không bắt buộc để làm cho nó ngừng chạy. Ngoài ra, nó dừng chạy khi hệ thống hết bộ nhớ. Khi bash kết thúc, bằng SIGTERM hoặc do hết bộ nhớ, bộ nhớ sẽ được đưa trở lại hệ điều hành.
foobar

Điều này không hiệu quả với tôi ... đại loại là ... tôi có thể thấy bộ nhớ dần biến mất, nhưng điều này xảy ra rất chậm, và nó cũng có thể bị giết bằng cách chỉ cần nhấn ctrl + c. Nó chạy được 1 phút và chiếm khoảng 1GB. Tôi có một máy RẤT nhanh ... nhưng điều đó không thành vấn đề, phải không?
Stefanos Kalantzis

Trả lời nhận xét của riêng tôi: Lệnh thực sự đã giết chết bash sau khoảng 2 phút 49 giây. Ban đầu tôi cho rằng nó sẽ ngay lập tức dựa trên câu trả lời này.
Stefanos Kalantzis

@StefanosKalantzis Cảm ơn ý kiến ​​của bạn. Nó làm tôi suy nghĩ nhiều hơn một chút và tôi chỉ tìm thấy một đoạn vỏ thậm chí còn ác hơn - xem chỉnh sửa.
Chấn thương kỹ thuật số

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

Sau đó chuyển tài liệu tới trình phân tích cú pháp XML không thực hiện phát hiện vòng lặp / đệ quy tham chiếu thực thể. Ví dụ, xpathbao gồm với perl:

xpath boom.xml /

Làm thế nào nó hoạt động:

  1. Trình phân tích cú pháp gặp phải <boom a="&a;">
  2. Trình phân tích cú pháp mở rộng "&a;"thành"&b;&b;"
  3. Các phân tích cú pháp mở rộng là một trong những "&b;"thành "&c;&c;"(khi trở về, nó sẽ mở rộng khác "&b;")
  4. Trình phân tích cú pháp mở rộng một trong những "&c;"...

Nếu mở rộng hoàn toàn có thể xảy ra, sẽ có 2 ^ 52 bản mở rộng "ka-boom!". Giả sử 2 byte cho mỗi ký tự, nó sẽ cố gắng sử dụng 64 PiB. Việc mở rộng đi "ka-boom!" tại một thời điểm, vì vậy bạn thường có thể xem nó sử dụng hết bộ nhớ trong đầu.

Điều này có nhiều tên khác nhau, tổng quan tốt ở đây: http://projects.webappsec.org/w/page/13247002/XML%20Entity%20Expansion


3
Về cơ bản là một bản sao của Tỷ cười
Cole Johnson

@ColeJohnson Yup đó là nó! Tôi đã đóng góp cho dự án Phân loại mối đe dọa của WASC, vì vậy tôi cảm thấy bắt buộc phải chỉ đến WASC chứ không phải Wikipedia. :)
ɲeuroburɳ

22

C ++

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

Mã này thật bất ngờ! Nó treo máy tính của tôi trong khi trình quản lý tác vụ đang mở và cho thấy rằng nó mất 890 Mb bộ nhớ trong 1 giây thì nó cũng bị treo. Tôi không biết cách thức hoạt động của nó, có thể nó tiếp tục cung cấp bộ nhớ cho một biến. Để khám phá thêm về mã này, tôi đã thêm một tuyên bố delete a;và mọi thứ đều ổn trong khi thử nghiệm (không bị treo) Vì vậy, tôi nghĩ rằng khối bộ nhớ là đã cho (do new int) và sau đó được đưa trở lại (do delete a) vào không gian trống trong mã mới bên dưới.

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

Vì vậy, tôi kết luận rằng KHÔNG CÓ RAM TRONG THẾ GIỚI NÀY CÓ THỂ XỬ LÝ MÃ NÀY !!!

EDIT : Nhưng nhiều bộ xử lý có thể, ví dụ như intel core 2 duokhông thể xử lý mã này nhưng
intel core i-seriescó thể (làm việc cho tôi ...)

Hãy nhớ câu trả lời cho câu hỏi là mã thứ 1, mã thứ hai là để giải thích.


9
Thật tuyệt, trình biên dịch nghĩ rằng bạn vẫn sẽ sử dụng new intmặc dù bạn đã ghi đè con trỏ, vì vậy bạn không bao giờ có thể truy cập lại ... Vì vậy, không có bộ sưu tập rác nào được gọi và bạn lấp đầy bộ nhớ nhanh hơn một đứa trẻ béo ăn skittles
David Wilkins

37
@DavidWilkins: ... đây là C ++, C ++ không có trình thu gom rác.
Phoshi

32
Nếu bạn bất ngờ rằng mã này bị rò rỉ, thì tôi nghĩ bạn không nên sử dụng C ++ cho đến khi bạn học nó tốt hơn.
Svick

1
@svick Nhưng nó cũng không giống như đánh phi tiêu trong bóng tối! Tôi đã có một số ý tưởng rằng điều này sẽ làm câu hỏi công việc muốn.
Mukul Kumar

15
@svick Làm thế quái nào mà anh ta phải 'học nó tốt hơn' nếu anh ta 'không nên sử dụng C ++'?
Kevin

16

BrainFuck

+[>+]

Giải trình:

Để vào vòng lặp, nó tăng ô lên 1. Nó di chuyển đến ô tiếp theo tăng lên 1 miễn là ô cuối cùng dương.

Thông thường Trình thông dịch BrainFuck thiếu sót khi có giới hạn cứng đối với số lượng ô trên băng, nhưng một số trình thông dịch thêm các ô một cách linh hoạt. Những thứ này sẽ tiếp tục tiêu thụ bộ nhớ cho đến khi nó không còn tiêu thụ nữa.

beeflà một trình thông dịch như vậy và nó có sẵn trong Trung tâm phần mềm Ubuntu và hoạt động hiện tại của tôi trên một máy chưa sử dụng đã bắt đầu 29 giờ trước và đã tiêu tốn 1GB RAM trong thời gian đó. Đây là đầu ra củatop

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

Nó có 4GB bộ nhớ cache và 6GB trao đổi, vì vậy tôi đoán tôi sẽ cập nhật câu trả lời này với cách nó diễn ra trong khoảng 12 ngày.

CẬP NHẬT 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    

CẬP NHẬT 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   

Vì vậy, nó đã chạy được 10 ngày. Có vẻ như nó sẽ chạy thêm ít nhất 10 lần nữa trước khi điều gì đó thú vị xảy ra.


Đẹp và ngắn.
nrubin29

15

C và POSIX

Ở đây tôi đang hướng đến một giải pháp rất di động. Vấn đề là C thuần túy dường như không có cách nào để nói với Hệ điều hành rằng bộ nhớ sẽ vẫn được phân bổ sau khi chương trình đóng lại. Vì vậy, tôi cho phép mình sử dụng POSIX; Hầu hết các hệ điều hành đều có một số yêu cầu về khả năng tương thích POSIX bao gồm Windows, Linux và MacOS X. Tuy nhiên, tôi mới chỉ thử nghiệm nó trên Ubuntu 12.04 32bit. Nó không yêu cầu quyền superuser.

Giải pháp này thực chất là while(1){malloc(1);}giải pháp truyền thống . Tuy nhiên, thay vì malloc, nó sử dụng các chức năng bộ nhớ chia sẻ POSIX. Vì nó gán một định danh bộ nhớ dùng chung cho mỗi cấp phát, nên vẫn có thể truy cập vào bộ nhớ sau khi quá trình kết thúc. Do đó, kernel không thể giải phóng bộ nhớ.

#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âu trả lời C hay nhất và xuất sắc nhất IMO. +1
syb0rg

1
Đẹp một. Giải pháp đầu tiên tôi đưa ra là của Andrew Medico, nhưng vì điều đó không thể có trên Linux và vì tôi không thích lập trình Windows, tôi muốn rò rỉ qua bộ nhớ dùng chung, nhưng không thể nhớ tên hàm POSIX. Cảm ơn vì đã nhớ đến tôi về chúng;) Tất cả những gì tôi tìm thấy chỉ là những thứ không thể tách rời khi chấm dứt quá trình ...
foobar

14

C #

Việc quên hủy đăng ký khỏi các sự kiện trước khi trình xử lý vượt quá phạm vi sẽ khiến .NET bị rò rỉ bộ nhớ cho đến khi nó ném 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;
    }
}

Giải thích : Bên trong whilevòng lặp, chúng tôi xây dựng một đối tượng mới, làm cho khung phân bổ thêm bộ nhớ, nhưng chúng tôi cũng ngăn chặn trường hợp mới Bđược giải phóng khi nó vượt ra ngoài phạm vi bằng cách gán một phương thức cá thể cho một sự kiện trong một lớp khác, kết quả là trường hợp mới Btrở nên không thể truy cập được từ mã của chúng tôi, nhưng một tài liệu tham khảo vẫn tồn tại, có nghĩa là GC sẽ không phát hành nó cho đến khi avượt ra ngoài phạm vi.

Các sự kiện tĩnh có cùng một cạm bẫy, vì chúng không bao giờ vượt quá phạm vi, chúng chỉ được dọn sạch khi quá trình kết thúc, trừ khi bạn hủy đăng ký khỏi sự kiện trước. Luôn luôn lưu trữ tài liệu tham khảo của bạn, mọi người!

using System;

class Program
{
    static event Action Event;

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

Ở trên hoạt động trên cùng một ý tưởng, trình xử lý trở nên không thể truy cập được khi whilevòng lặp vượt quá phạm vi, khiến cho không thể hủy đăng ký khỏi sự kiện, có nghĩa là bộ nhớ sẽ nằm ở đó cho đến khi chương trình kết thúc. Các sự kiện tĩnh được cho là nguy hiểm hơn các sự kiện cá thể, bởi vì bạn có thể đảm bảo chúng không bao giờ vượt quá phạm vi.

EDIT : Về cơ bản, bạn cũng có thể làm tương tự với bất kỳ đối tượng nào khác, miễn là bạn thêm một tham chiếu đồng thời đảm bảo không có cách nào để giải phóng tham chiếu đó.

Đây là một ví dụ sử dụng các đối tượng và mảng tĩnh.

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

Mảng tiếp tục được thêm vào danh sách, nhưng không có cách nào để xóa danh sách mà không sửa đổi mã, điều này là không thể đối với các ứng dụng nguồn đóng. Việc tăng số lượng được truyền vào Leak.Addsẽ khiến nó bị rò rỉ nhanh hơn, nếu bạn đặt nó đủ cao, nó sẽ chỉ dẫn đến một OverflowException ngay lập tức bị ném.


10

bash (không có tiện ích bên ngoài)

Không có bom ngã ba ở đây.

Cảnh báo: Nó có thể giết chết vỏ của bạn.

Chỉ cố gắng tạo ra một loạt các số nguyên để tham khảo vì tôi cứ quên mất rằng số nguyên trông như thế nào.

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

Kết quả trong:

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

2
+1 cho "vì tôi cứ quên mất số nguyên trông như thế nào" :)
David Conrad

8

J (7)

CẢNH BÁO: Điều này đóng băng hệ thống của tôi khi tôi thử nó (Windows 8, J 8.01, trong thiết bị đầu cuối qt).

2#^:_[_
  • 2# nhân đôi độ dài của đối số bằng cách nhân đôi từng phần tử,
  • ^:_ tìm điểm cố định của hàm đã cho (nhưng không có điểm nào để nó lặp lại vô tận),
  • [_gọi nó với _tư cách là đối số.

8

Haskell (số của Graham)

Rất đơn giản: điều này tính toán số của Graham

Không giống như các ví dụ khác ở đây, nó sẽ không chạy mãi mãi ... nó sẽ sử dụng rất nhiều cpu, nhưng về mặt lý thuyết nó có thể chấm dứt. nếu thực tế là không lưu trữ số ...

vũ trụ quan sát được là quá nhỏ để chứa một đại diện kỹ thuật số thông thường của số Graham, giả sử rằng mỗi chữ số chiếm một khối lượng Planck .

(theo wikipedia)

import Data.Sequence
import Data.Foldable

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

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

Vì vậy, ý tưởng là bộ nhớ sẽ được sử dụng bởi (một loạt các ngày càng lớn Integer) (Số nguyên của Haskell có kích thước tùy ý).

Nếu bạn muốn kiểm tra nó, bạn có thể phải tăng kích thước ngăn xếp hoặc tải nó vào bên trong ghci.


2
Vũ trụ câm, không tuân theo tiêu chuẩn Haskell cho Số nguyên. Tại sao nó không thể hỗ trợ kích thước tùy ý?
PyRulez

6

Lấy cảm hứng từ @comitern.

Thay thế / dev / null. Tham gia chế độ lén lút. Yêu cầu tiêu đề kernel, chế độ siêu người dùng và trình biên dịch làm việc.

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

Chúc vui vẻ.

Trang điểm:

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

Mã nguồn:

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

Cảnh báo điều này có thể buộc bạn phải khởi động lại!

Để loại bỏ nó:

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

6

Hồng ngọc

Mọi người đều biết rằng tổng (1 / n ^ 2) = pi ^ 2/6

Vì vậy, tôi có thể định nghĩa một hàm gần đúng:

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

p pi_approx.(100_000)

Tất nhiên (1..infinity) sẽ chạy hoang dã.

Tuy nhiên, lưu ý rằng sử dụng lười biếng sẽ làm cho công việc này;)

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 ký tự (chương trình đầy đủ)

Đừng chạy cái đó, nếu không hệ thống của bạn sẽ nhanh chóng bị đóng băng!

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

Cuộc gọi đến malloc sẽ dành 9 byte bộ nhớ và yêu cầu các trang bộ nhớ mới từ hệ điều hành thường xuyên. Bộ nhớ được cấp phát bởi malloc ngay lập tức bị rò rỉ vì không có con trỏ đến địa chỉ được trả về được lưu trữ. Khi hệ thống hết bộ nhớ (RAM và dung lượng trao đổi) hoặc đạt đến giới hạn bộ nhớ cho quá trình, chương trình sẽ thoát ra khỏi vòng lặp while và chấm dứt.


2
Không lâu đâu - bất kỳ hệ thống hợp lý hiện đại nào cũng cần có một kẻ giết người OOM tấn công và giết chết quá trình. Ít nhất Ubuntu 12.04 cũng vậy.
Chấn thương kỹ thuật số

1
Chà, tôi đã làm hỏng Ubuntu 13.10 trong khi thử mã này ...
Mathieu Rodic

@DigitalTrauma Ví dụ: FreeBSD có OOMK không?
Ruslan

1
main(){while(malloc(9));}lưu lại 3 ký tự khác và lấp đầy bộ nhớ của tôi ngay lập tức.
gmatht

@gmatht: cảm ơn vì lời đề nghị! Tôi đã chỉnh sửa câu trả lời ... mặc dù tôi thích ý tưởng tăng kích thước của khối trên mỗi vòng lặp.
Mathieu Rodic

4

VBScript

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

Chúng tôi đang tạo ra một dicionary chỉ vào chính nó. Sau đó, chúng tôi nghĩ rằng chúng tôi phá hủy từ điển bằng cách đặt nó thành Không có gì. Tuy nhiên, từ điển vẫn tồn tại trong bộ nhớ vì nó có tham chiếu (vòng tròn) hợp lệ.

Vòng lặp, nhưng cũng là bộ nhớ hog, khiến chương trình bị treo. Sau khi tắt chương trình, bộ nhớ vẫn được sử dụng. Hệ thống chỉ có thể được khôi phục bằng cách khởi động lại nó.


Uh, thật sao? VBScript không chỉ sử dụng VB.NET dưới mui xe? Các tài liệu tham khảo thông thường không phải là vấn đề đối với người thu gom rác, ngoại trừ việc triển khai số tham chiếu đơn giản và việc chấm dứt chương trình sẽ dẫn đến việc phát hành toàn bộ đống của nó , phải không?
David Conrad

@DavidConrad Bạn sẽ nghĩ vậy, nhưng tôi phải khởi động lại máy mỗi lần tôi điều tra cái này và chạy loại script này.
AutomatedChaos

1
VBScript có trước VB.Net đáng kể - nó không phải là phiên bản dòng lệnh của VB.Net; nó là một tập hợp con được giải thích của Visual Basic.
Chris J

Cảm ơn cả hai bạn. Tôi không nhận ra mối quan hệ giữa VBScript và VB.NET là gì.
David Conrad

4

Có & tmpfs

Tại sao lại viết một chương trình mới khi một chương trình miễn phí với Ubuntu?

yes > /run/user/$UID/large_file_on_my_ramdisk

Như bạn có thể biết, hoặc đã đoán, Ubuntu gắn kết / chạy / người dùng / theo mặc định là một tmpfs là một loại đĩa RAM .

Bạn thậm chí không phải đóng nó. Nó sẽ lịch sự đóng lại, để lại một đoạn ký ức đẹp được phân bổ. Tôi đoán yeslà một chương trình xử lý đơn, một luồng mà không gọi bất kỳ chương trình nào khác (ghi vào đĩa RAM hiện tại cũng có thể di chuyển tầm thường theo ngôn ngữ bạn chọn).

Nó có một lỗi nhỏ: Ubuntu giới hạn người dùng có thể ghi tmpfs / run / 1000 đến 100 MB theo mặc định, do đó, tính năng chết trao đổi có thể không được hỗ trợ trên máy của bạn. Tuy nhiên, tôi đã cố gắng khắc phục sự cố này trên máy của mình bằng cách khắc phục nhanh sau đây:

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

Tôi không có một /run/userthư mục nào cả. Phiên bản Ubuntu nào bạn sử dụng và bạn đã cài đặt cái gì cho việc này?
Ruslan

Ubuntu Trusty Tahr (14.04). Không cần cài đặt đặc biệt.
gmatht

Để tìm xem bạn có bất kỳ tmpfshệ thống tập tin nào được gắn kết hay không, bạn có thể liệt kê chúng với df -t tmpfs. Hệ thống Ubuntu của tôi /run/shmcó sẵn rất lớn ...
Toby Speight

4

Bash

Cảnh báo: Đoạn mã sau sẽ khiến máy tính của bạn không thể khởi động.

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

Cảnh báo: Mã trước sẽ làm cho máy tính của bạn không thể khởi động.

Thay thế / dev / sda với ổ đĩa khởi động của bạn. Điều này ghi E8 FD FF vào sự cầu xin của khu vực khởi động của bạn. Khi khởi động, BIOS đọc khu vực khởi động của bạn vào bộ nhớ và thực thi nó. Những opcodes tương đương với hội đồng này:

label:
  call label

Đây là đệ quy vô hạn, cuối cùng sẽ gây ra tràn ngăn xếp.


Trong ví dụ về hội của bạn, bạn có thể lưu một ký tự (giả sử tên "nhãn" là cần thiết) bằng cách sử dụng jmpthay vìcall
SirPython

gọi để lại địa chỉ trả về trên ngăn xếp cho ret. nhảy sẽ không gây ra một chồng tràn.
Jerry Jeremiah

3

Haskell

main=print $ sum [0..]

Điều này cố gắng để thêm số đếm. Haskell đánh giá các khoản tiền một phần, nó chỉ trở thành một tuyên bố bổ sung vô hạn. Nếu bạn chạy trình biên dịch với các cờ tối ưu hóa, nó có thể không hoạt động.


3

Bash

Vì chúng ta có thể sử dụng các tiện ích không được thiết kế riêng để tiêu thụ bộ nhớ, tôi tập trung vào một tiện ích để giải phóng bộ nhớ : swapon. Điều này được sử dụng để cho phép kernel giải phóng bộ nhớ bằng cách ghi vào đĩa.

Kịch bản lệnh này thực hiện hai tối ưu hóa: (1) Gắn tmp dưới dạng tmpfs (một loại đĩa RAM) để tạo / tmp nhanh hơn và (2) tạo tệp hoán đổi để giải phóng bộ nhớ. Mỗi cái đều hợp lý nhưng nếu người dùng bất cẩn thực hiện cả hai thì nó sẽ thiết lập một chu kỳ hoán đổi: khi HĐH cố gắng hoán đổi các trang, nó sẽ ghi vào tmpfs; điều này làm cho các tmpfs sử dụng nhiều bộ nhớ hơn; điều này làm tăng áp lực bộ nhớ khiến nhiều trang bị tráo đổi. Việc này có thể mất vài phút trên máy ảo của tôi, rất nhiều thời gian để bạn xem hệ thống tự đào lỗ hổng top.

Đóng chương trình tạo ra ít khác biệt vì bản thân chương trình phân bổ hầu như không có bộ nhớ. Thật vậy, nó không tầm thường đối với bộ nhớ trống vì bạn không thể giải phóng bộ nhớ bằng cách ngắt kết nối các tmpfs trước khi bạn swapofftrao đổi, và điều đó khó thực hiện cho đến khi bạn giải phóng bộ nhớ.

Câu trả lời này có thể được coi là một câu chuyện cảnh báo chống lại việc áp dụng các thủ thuật hay từ mạng mà không hiểu chúng.

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

Sử dụng tài liệu tham khảo thông tư. Tổng số tham chiếu cho các biến sẽ không bao giờ đạt đến 0 và các tham chiếu sẽ không bao giờ được thu gom rác.

Bạn có thể cần phải kiên nhẫn, nhưng nó được đảm bảo để làm nghẹt hệ thống của bạn. Đĩa sẽ bắt đầu quay nhanh hơn và có thể nhìn thấy khói.


2

PHP (chỉ dành cho linux):

Mã này chưa được kiểm tra, vì tôi không có máy tính linux đang chạy php.

Nhưng đây là bằng chứng về khái niệm của tôi:

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

Điều này sẽ lấp đầy bộ nhớ với hình ảnh RGBA khổng lồ (10000x10000 pixel).

Cách duy nhất để tắt em bé này là tắt nguồn.

Các mã là tất cả nhận xét.

Bất kỳ cải thiện, nghi ngờ, lỗi hoặc bất cứ điều gì, sử dụng hộp bình luận bên dưới.


Bất cứ ai có quyền truy cập vào tâm trí linux kiểm tra nó? Cảm ơn :)
George

Tôi có linux, tôi chỉ không chắc nó sẽ hoạt động như thế nào. Tôi đã cung cấp màn hình in cho câu trả lời đầu tiên, nhưng đó là một phiên bản thực sự cũ của puppy linux. Ubuntu quá chậm để chạy php. Có lẽ tôi sẽ thử nghiệm trên Android của mình sau này.
Ismael Miguel

1
nó không thành công khi không gọi một chương trình khác
Einacio 21/03 '

Nó không gọi một chương trình khác: nó gọi cùng một chương trình đã khởi động tệp cho cùng một tệp.
Ismael Miguel

2

Con trăn - 56

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

Tạo một lớp, định nghĩa một phương thức để thiết lập các thuộc tính, đặt một thuộc tính trong đó và tạo một thể hiện ban đầu mà sau đó nó cố gắng đặt một thuộc tính.

Một hàm đệ quy đơn giản ( def f(x):f(x)) có vẻ hơi không tưởng tượng nên tôi quyết định không bao giờ thực sự gọi một hàm.

Quản lý bộ nhớ có thể bắt được độ sâu đệ quy, nhưng nó thực sự phụ thuộc vào việc thực hiện.

Nếu đây là một quả bom ngã ba, xin vui lòng cho tôi biết.


4
Điều này gây ra sự cạn kiệt bộ nhớ, chỉ là : RuntimeError: maximum recursion depth exceeded while calling a Python object. Ngay cả việc thiết lập giới hạn đệ quy tối đa mà sys.setrecursionlimithầu như không sử dụng bộ nhớ trước khi nó gặp sự cố với lỗi phân đoạn.
Bakuriu

@Bakuriu Giống như tôi đã nói, nó thực sự phụ thuộc vào việc triển khai (có các triển khai Python chuyển đổi thành C (++) và biên dịch, ví dụ Shed leather, Nuitka).
cjfaure

2
Sau đó nêu rõ (các) triển khai cụ thể mà bạn đang viết mã. Có một sự khác biệt giữa các thách thức trong đó chỉ có vấn đề cú pháp và do đó việc triển khai không liên quan và các thách thức hoàn toàn phụ thuộc vào cách ngôn ngữ được triển khai.
Bakuriu

2

Perl

Đó là một điều đơn giản, nhưng tôi cảm thấy như chơi golf.

{$x=[$x];redo}

Sau hai lần lặp, $xchứa tham chiếu đến mảng chứa tham chiếu đến mảng chứa undef.

Việc sử dụng bộ nhớ là tuyến tính theo thời gian, với các phân bổ nhỏ, nhưng chỉ mất vài giây để làm chậm nghiêm trọng trình quản lý cửa sổ của tôi trên hệ thống Ubuntu Linux của tôi. Nửa phút sau, kẻ giết người OOM đã chăm sóc nó.


2

Bản thảo 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)

Ung dung:

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

Lưu ý: Nó sử dụng setTimeout, được định nghĩa là một phần của Bộ hẹn giờ - Tiêu chuẩn sống HTML .

Hãy dùng thử trên Mozilla Firefox (bạn có thể dán nó vào bảng điều khiển dành cho nhà phát triển). Firefox tiếp tục chiếm nhiều bộ nhớ hơn và sử dụng 100%CPU trên máy một lõi (trên máy 4 lõi, như của tôi, nó sử dụng 25%CPU). Nó cũng có thêm lợi ích mà bạn không thể dừng lại; nếu bạn có thể mở trình quản lý tác vụ, bạn có thể giết Firefox bằng nó.


1
Nó sử dụng 100% lõi. Trên bộ xử lý quadcore của bạn, điều đó dẫn đến 25% mức sử dụng CPU.
Iván Pérez

@Electrosa Vâng, bạn hoàn toàn chính xác. Tôi đã cập nhật câu trả lời của mình.
Bàn chải đánh răng

Đây không phải là một câu hỏi golf mã, xin vui lòng cố gắng làm cho mã của bạn có thể đọc được.
Paŭlo Ebermann

@ PaŭloEbermann OK. Tôi đã đăng một phiên bản chưa được chỉnh sửa.
Bàn chải đánh răng

1

Bash

Tạo một tệp trống test
Thay thế /dev/null/bằng tệp văn bản này

$ sudo mv test /dev/null

Điều này hoạt động theo cách tương tự như câu trả lời của @ Comi INTERN. Tất cả đầu ra /dev/nullbây giờ sẽ được thêm vào tệp văn bản này, theo thời gian sẽ trở nên rất lớn và làm sập hệ thống.


1
Một tập tin lớn sẽ không sụp đổ hệ thống. Và giả sử kích thước đĩa trung bình là 500gb, sẽ mất nhiều thời gian để tập tin thậm chí đến gần để lấp đầy đĩa.
w4etwetewtwet

1
Trên các hệ thống /devlà một devtmpfs, nó có thể lấp đầy và cản trở hệ thống. Tôi đoán đó là ý định của câu trả lời này.
Toby Speight

1

Bash: 7 ký tự

Đây phải là giải pháp bash đơn giản nhất. Không dĩa, không gian lận.

x=`yes`

Bạn không nên chạy cái này như root.


Lưu ý bổ sung: ngay cả khi bạn chấm dứt điều này với ctrl-c giữa chừng, và sau đó unsetlà biến, bộ nhớ vẫn được phân bổ cho đến khi shell bị giết. Bạn có thể xem các cuộc tàn sát trong top.
Bạo loạn

Các thử nghiệm của riêng tôi với bash 4.2,45 (1) cho thấy unset xkhông có bộ nhớ. pdksh cũng giải phóng bộ nhớ, nhưng ksh93 không giải phóng được nó, và exittrong lõi của ksh93.
hạt nhân

Đối với tôi (bash 4.3.11 (1)), bộ nhớ thường trú hiển thị trên cùng cho vỏ cha mẹ tăng dần đều cho đến khi yesbị giết, tại thời điểm nó chỉ ở đó, unsetkhông có hiệu lực. Nhưng đây là trên một hệ thống bộ nhớ lớn và có một biến là vài gigabyte dường như không gây rắc rối cho nó (cho đến khi cuối cùng nó quyết định giết vỏ).
Bạo loạn

0

C

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

Vâng, nó mất trang bộ nhớ sau trang và cuối cùng không còn bộ nhớ.


Làm thế nào phổ quát là một trang là 4 KB?
Peter Mortensen

@Peter 4K thường có kích thước, nhưng tôi không thể biết nó có thực sự phổ biến hay không, nhưng kích thước trang không có mối quan hệ với câu hỏi nhất định.
ST3

1
@ ST3: Bạn nên làm bẩn trang bộ nhớ. Hầu hết các hệ điều hành hiện đại sử dụng bộ nhớ ảo và chỉ tạo một bản ghi trong bảng bộ nhớ ảo, khi bạn phân bổ bộ nhớ. Viết một byte đơn vào trang bộ nhớ sẽ buộc hệ điều hành ánh xạ trang bộ nhớ ảo thành bộ nhớ vật lý.
foobar


0

Hồng ngọc

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

Nó chỉ nối thêm vô tận (đệ quy!) Tự tham chiếu đến chính nó.

Phát hiện ra viên ngọc nhỏ này khi ai đó phá vỡ hộp cát Ruby của tôi với nó . :CƯỜI MỞ MIỆNG

Bản trình diễn các khía cạnh đệ quy của nó:

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

Không chơi gôn

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

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

Tôi đã sửa mục nhập của tôi để bao gồm cuộc gọi từ chính.


Đây là một cuộc thi phổ biến. Nếu chương trình hoạt động giữ cho nó là chính và tiêu đề. tốt rồi. Ngoài ra, bạn có thể đăng một phiên bản không chơi golf? Cảm ơn :)
George
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.