Çatal bombaları olmadan [kapalı] bir hafıza sızıntısı oluşturun


54

Göreviniz bir bellek sızıntısı oluşturmaktır . Bu, bilgisayar tükenene ve kendini tükenmekten kurtarmak için bazı takası yapmak zorunda kalana kadar, çok miktarda bellek kullanan bir programdır. Belleğin serbest bırakılmasının tek yolu, programı görev yöneticisinde öldürmek taskkill /im yourprogram /fveya (Windows'ta) gibi bir komut satırı öldürmek veya bilgisayarı yeniden başlatmaktır. Uygulamanın yalnızca kapatılması, hafızanın devam etmesini engellememelidir.

Kurallar:

  1. Her türlü çatal bomba yasaklandı. Bu rezil Bash hattının :(){ :|:&};:yasaklandığı anlamına geliyor !

  2. Uygulama sadece tek iş parçacıklı olmalıdır. Bu, çatal bomba kuralını ima eder.

  3. Program başka programlar çalıştırmamalıdır. Bu, sadece böyle bir şey yapamayacağınız anlamına gelir run(memoryfiller.exe). Bunun tek istisnası, işletim sisteminizle veya dilinizle birlikte verilen ve öncelikle bellek tüketmek için tasarlanmamış olan programlardır (başka bir amacı vardır). Bu, şeylerin hoşuna gittiği catve ln -sizin verildiği anlamına gelir .

  4. İstediğiniz kadar bellek alabilir. Ne kadar çok, o kadar iyi.

  5. Kod tamamen açıklanmalıdır.

İyi şanslar. Bu bir popülerlik yarışmasıdır, bu nedenle en geç oy alan kod 10 gün sonra kazanır!


8
"Kapatılıyor, hala bellek belleği olmalıdır" - bir program çalıştırılabilir bir kabuksa (kodlama dili yorumlayıcılarının çoğu Windows sürümleri gibi), penceresini kapatmak programı öldürür.
Mart'ta

54
Bu sadece değil while(1)malloc(999);mi?
Doorknob

10
"Kapatmak hala hog hafızayı sağlamalıdır" ile uyumlu olup olmadığından emin değilim "Uygulama yalnızca tek iş parçacıklı olmalıdır". Hiçbir iş parçacığında bellek yığını yoksa, işletim sistemi geri alabilir, değil mi?
aebabis

51
Sadece birkaç saat boyunca firefox 26 ile yarım saat boyunca akan flaşı çalıştırın. Bilgisayarınızı dizlerine getirir.
Braden Best

1
@mniip. Bu meydan okuma meselesi. Zor bir meydan okuma yapmak için. Ve kapı tokmağı. Farklı bir şey istedim! ;)
George

Yanıtlar:


78

pencereler

Win32 API, diğer işlemlerde bellek ayırmanıza ve daha sonra bu belleği uzaktan okumanıza / yazmanıza izin verir. Bu program, sistemdeki her çalışan işlemi numaralandırmak için kullandığı ve ardından tahsis işlemi başarısız olana kadar her işlemde 1MB arabellekleri art arda ayırmak için kullandığı yalnızca bir iş parçacığına sahiptir. Bir işlemle bitince, bir sonrakine geçer. Çağıran program bittiğinde tahsisler serbest bırakılmaz - yalnızca her hedef işlem bittiğinde /. Bu 2GB'lık bir Windows 7 VM'yi yaklaşık 10 saniye içinde kapatıyor. Yönetici olarak çalışmayı gerektirir.

Derlemek için: 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 kötüdür.
14'te

4
Bu gece kapatmam gerekiyor. Bu bir gitmek veremem;)
George

1
"(normal bir kullanıcı olarak çalışıyor, yönetici ayrıcalıklarını kullanmıyorsunuz") - bundan emin değilsiniz, varsayılan olarak normal kullanıcı belirtecinde bulunmayan SeDebugPrivilege'e ihtiyacınız var
rkosegi 21.03

@rkosegi Teşekkürler, düzeltildi.
Andrew Medico

14
+1 Bu , bugüne kadar birçok yükseltmeyi hak ediyor , çünkü orijinal Kapanış'ı karşılayan tek cevap, hala bellek gereksinimi haline getirmeli. Çok yaratıcı bir çözüm :-)
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();
    } 
  }
}

açıklama

Kodda referans olmadığından ( countgüvenle ihmal edebileceğiniz dışında) sızıntı yapamayacağını varsayabilirsiniz . Ancak, sonlandırıcı iki yeni Hydras yaratır ve bunlar için referanslar bulundurmazken, sonlandırılıncaya kadar etrafta dolanırlar. Bu, programın çöp toplama işlemi sırasında yalnızca belleği sızdırdığı anlamına gelir - bu nedenle System.gc()ve System.runFinalization().


7
@TimS. Tanrın şimdi nerede?!?
Cruncher

Are System.gc()ve System.runFinalization()gerekli? Bu bazen gc rasgele çalışacak mı, yoksa bir miktar belleği doldurmanız veya gc'yi çağırmanız mı gerekiyor?
Cruncher

4
Tipik bir programda System.gc()ve System.runFinalization()gerekli olmaz. Çöp toplama, bellek baskısı nedeniyle doğal olarak gerçekleşir. Ancak bu uygulamada çöp toplama işlemi çalışmaya başlayana kadar herhangi bir hafıza basıncı yoktur. Yapay olarak bazılarını tanıtmayı düşündüm (örneğin, new Hydra()döngünün içinde hareket ederek), ancak bunun daha kötü olduğunu düşündüm.
James_pic

1
Evet, anlamlı gözükmediği için (@ hala onu kapamak için hafızaya almalı) uyarısına çok fazla dikkat etmedim (@ german_guy's gibi temiz işletim sistemi hack'leri dışında). Java her zaman bir sonlandırma iş parçacığı oluşturur, bu nedenle belki de bir Java uygulamasının kural 2'ye uyması mümkün değildir.
James_pic

1
Unix sistemlerinde, SIGKILL'i engelleyemezsiniz (sinyal 9), bu nedenle programınızı durdurulamaz hale getiremezsiniz (peki, onu kesintisiz bir bekleme durumuna getirmeyi başaramazsanız hariç ... belki de dosyaları olan bir NFS sunucusunu uzaktan öldürmek erişim işe yarayabilir ;-))
celtschk

37

C

C programlama dilini kullanarak ve Linux çekirdeği 2.6.32-49-generic ve libc-2.11.1.so ile test edilmiştir.

Belleğin serbest bırakılmasının tek yolu, programı görev yöneticisinde öldürmek ya da program / f görev görevini kullanmak veya bilgisayarı yeniden başlatmaktır.

Bu, SIGKILL ve SIGSTOP dışındaki tüm sinyalleri engelleyerek elde edilir.

Kapatılması hâlâ domuz hafızasında kalmalı.

Bu aslında kafamı karıştırdı ... Her ikisini de öldürmek veya kapatmak, işlem sisteminin işlem tarafından tahsis edilen herhangi bir hafızayı geri talep etmesine izin vererek sürecin sonlandırılmasıyla sonuçlanır. Fakat daha sonra, onu kapatarak, terminalin veya hafıza sızıntısı işlemini gerçekleştiren herhangi bir ana sürecin kapatılması anlamına gelebileceğini düşünmeliyim. Bunu doğru yaparsam, bu sorunu, ana işlem sonlandırıldığında işlemi bir arka plana dönüştüren sinyalleri engelleyerek çözdüm. Bu şekilde işlemin çalıştığı terminali kapatabilirsiniz ve çalışmaya devam eder ve hafızaya sızmaya devam eder.

Her türlü çatal bomba yasaklandı. Yani rezil bash: () {: |: &} ;: yasaklandı!

İşlem çatal değil.

Uygulama sadece tek diş açılmalıdır. Bu çatal bomba kuralını ima ediyor

Yeni konu oluşturulmaz.

Program başka bir program çalıştırmamalıdır. Bu, sadece run (memoryfiller.exe) gibi bir şey yapamayacağınız anlamına gelir

Hiçbir yeni süreç ortaya çıkmaz.

İstediğiniz kadar bellek alabilir. Ne kadar çok, o kadar iyi.

İşletim sisteminin sağlayabildiği kadar.

Kod tamamen açıklanmalıdır.

Kaynağa yorum eklendi.

Ve nihayet işte kod:

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

Bu programı devam ettirirseniz ne olacağıyla ilgilenen herkes için: 2GB RAM ve 4GB değiştirme alanına sahip test sistemimde RAM'in doldurulması ve değiştirilmesi yaklaşık 10 dakika sürdü. OOM katili çalışmaya başladı ve üç dakika sonra tüm süreçler öldürüldü. Hatta fare, klavye ve ekran bile sistem tarafından düşürüldü. /var/log/kern.log, öldürülmüş süreçler dışında, hiçbir faydalı bilgi göstermez.


Oom katilinin işlemi görmezden gelmesini ve bunun yerine hafızayı boşaltmak için masum süreçleri öldürmesini sağlamak için kaynağı düzenledim.
foobar

5
Bu programı devam ettirirseniz ne olacağıyla ilgilenen herkes için: 2GB RAM ve 4GB değiştirme alanına sahip test sistemimde RAM'in doldurulması ve değiştirilmesi yaklaşık 10 dakika sürdü. OOM katili çalışmaya başladı ve üç dakika sonra tüm süreçler öldürüldü. Hatta fare, klavye ve ekran bile sistem tarafından düşürüldü. /var/log/kern.log, öldürülmüş süreçler dışında, hiçbir faydalı bilgi göstermez.
foobar

Haha, bu harika! Bu açıklamayı cevabınıza düzenlemelisiniz. +1
Doorknob

1
Aşağı oylamadım, ancak kodun biçimlendirilebilmesi iyi olurdu, bu nedenle yorumları okumak için yatay kaydırma gerekmez.
Paŭlo Ebermann

2
1 için +1) giriş / çıkış cihazlarını teslim eden işlemlerin öldürülmesine neden olmak ve 2) kayıt defterlerinden izlenmesi zor bir program oluşturmak. Bu bıyık kıvrıcı şeytani seviyelerdir.
Kevin - Monica

29

Saf bash

Çatal bomba değil, söz veriyorum:

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

Çatal bombaya çok benziyor ve benzer bir özyinelemeli teknik kullanıyor, ancak çatal kullanmıyor. Elbette bu, kabuğunuzu bellekten çıkartacaktır, bu yüzden bu komutu yapıştırmadan önce yeni bir kabuk başlatmanız önerilir.

  • Denilen bir işlev tanımlayın :
  • İşlev, $@tekrarlı bir şekilde (arg list) iki katına çıkarak kendisini çağırır.
  • İşlev tanımından sonra, işlev :ilk arg ile çağrılır.:

Çıktı:

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

Bu cevabın önceki bir düzenlemesinde yaptım a=$(yes), ancak "Program başka bir program çalıştırmamalıdır" kuralını fark ettim, bu yüzden bashherhangi bir coreutils veya başka bir şey çağırmadan saf kullanmam gerekiyor .


İşte burada bir başkası:

LÜTFEN ÜRETİM MAKİNESİNİ BU ÇALIŞTIRMAYIN

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

Yine, bu bir çatal bomba değil - her şey bir iş parçacığı içinden çalıştırılıyor. Bu, Ubuntu VM'mi diz çökmelerine oldukça kolay bir şekilde getiriyor ve kurtarma için küçük bir oda var.

Klasik çatal bombada olduğu gibi özyinelemeli bir işlev :()tanımlanmıştır. Ancak kendi kendine çağrıları engellemez. Bunun yerine kendisini bir süreç ikamesinde adı verilen bir argümanla çağırıyor . İşlem değiştirme bir dosya tanımlayıcı açarak çalıştığından /dev/fd/n, bu yalnızca işlem (bash) belleğini yemez, aynı zamanda bazı çekirdek belleği de tüketir. Ubuntu makinemde bu, pencere yöneticisini birkaç saniye sonra, ardından bu ekrana geçtikten kısa bir süre sonra çalışamaz duruma getirme etkisine sahiptir:

enter image description here

OKSonra tıklamak bu ekranı verir:

enter image description here

Bu seçeneklerin hiçbiri pek yardımcı görünmüyor - bu noktada yeniden başlatma tek iyi seçenek gibi görünüyor.


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

2
"Belleğin serbest bırakılabilmesinin tek yolu, programı görev yöneticisinde öldürmek veya program / im'inizdeki görev kitini kullanarak veya hatta bilgisayarı yeniden başlatmaktır. Kapatılması hala bellek hafızası yapmalıdır." >> Bash, bir SIGTERM kullanılarak sonlandırılabilir, bu nedenle çalışmasını durdurmak için onu öldürmek gerekmez. Ayrıca sistem belleği yetersiz kaldığında çalışmayı durdurur. Bash, SIGTERM veya hafızamız tükenerek sona erdiğinde, bellek işletim sistemine geri verilir.
foobar

Bu benim için işe yaramıyor ... Bir çeşit ... Hafızanın yavaş yavaş gittiğini görebiliyorum, ama bu çok yavaş oluyor ve sadece ctrl + c tuşlarına basarak da öldürülebilir. Şimdi 1 dakika çalışıyor ve yaklaşık 1GB meşgul. ÇOK hızlı bir makinem var ... ama bunun önemi yok, değil mi?
Stefanos Kalantzis

Kendi yorumumu cevaplamak: Komut aslında 2mins 49sn sonra bash'ı öldürdü. Aslında bu cevaba dayanarak anında gerçekleşeceğini varsaydım.
Stefanos Kalantzis

@StefanosKalantzis Yorumlarınız için teşekkür ederiz. Biraz daha düşünmemi sağladı ve daha da kötü bir şeytan parçacığını daha yeni buldum - bkz. Düzenleme.
Dijital Travma

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

Ardından, belgeyi varlık referans döngüsü / özyineleme algılaması yapmayan bir XML ayrıştırıcısına iletin. Örneğin, xpathperl ile dahil:

xpath boom.xml /

Nasıl çalışır:

  1. Ayrıştırıcıyla karşılaşır <boom a="&a;">
  2. Ayrıştırıcı genişler "&a;"içine"&b;&b;"
  3. Ayrıştırıcı biri genişler "&b;"INTO "&c;&c;"(dönüş, diğer genişleyecektir "&b;")
  4. Ayrıştırıcı "&c;"vb biri genişletir ...

Tam genişleme gerçekleşirse, "ka-boom!" Un 2 ^ 52 genişlemesi olur. Karakter başına 2 bayt varsayarak, 64 PiB kullanmaya çalışır. Genişleme "ka-boom!" bir anda, böylece genellikle üstteki tüm belleği kullanmasını izleyebilirsiniz.

Bu, çeşitli isimlerle gider, burada iyi bir genel bakış: http://projects.webappsec.org/w/page/13247002/XML%20Entity%20Expansion


3
Temelde Billion'un bir kopyası gülüyor
Cole Johnson

@ColeJohnson Yup bu kadar! WASC Tehdit Sınıflandırması projesine katkıda bulundum, bu yüzden Vikipedi yerine WASC'ye işaret etmek zorunda olduğumu hissettim. :)
ɳeuroburɳ

22

C ++

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

Bu kod beklenmedik oldu! Görev yöneticisi açıkken bilgisayarımı kapattı ve 1 saniye içinde 890 Mb bellek aldığını ve ardından kapattığını gösterdi. Bunun nasıl çalıştığını bilmiyorum, belki de bir değişkene bellek vermeye devam ediyor. Bu kodun daha fazlasını araştırmak için bir ifade ekledim delete a;ve test ederken her şey iyiydi (askıda değil) Öyleyse, hafızanın bir parçası olduğunu düşünüyorum. verilen (nedeniyle new int) ve sonra delete aaşağıdaki yeni koddaki boş alana (nedeniyle ) geri alındı .

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

Bu nedenle, BU DÜNYADA RAM YOK BU KODU KULLANABİLİRSİNİZ !!!

EDIT : Ancak birçok işlemci örneğin intel core 2 duobu kodu kaldıramaz ancak
intel core i-seriesyapabilir (benim için çalıştı ...)

Unutmayın, sorunun cevabı 1. kod, ikincisi açıklama içindir.


9
Güzel, derleyici new int, işaretçiyi üzerine yazmanıza rağmen hala kullanacağınızı düşünüyor , böylece bir daha asla erişemezsiniz ... Yani hiçbir çöp toplama işlemi yapılmaz ve hafızayı şişman bir çocuktan daha hızlı doldururuz
David Wilkins

37
@DavidWilkins: ... Bu C ++, C ++ 'un çöp toplayıcısı yok.
Phoshi

32
Size bu kodun sızması beklenmiyorsa, daha iyi öğrenene kadar C ++ kullanmamanız gerektiğini düşünüyorum.
svick

1
@svick Ama aynı zamanda karanlıkta dart tahtası vurmak gibi değil! Bunun iş sorusunun istediği şeyi yapacağına dair bir fikrim vardı.
Mukul Kumar

15
@svick 'C ++' kullanmamalıysa, nasıl daha iyi öğrenmesi gerekiyor?
Kevin

16

brainfuck

+[>+]

Açıklama:

Döngüye girmek için hücreyi 1'e yükseltir. Son hücre pozitif olduğu sürece 1'e yükselterek bir sonraki hücreye geçer.

Genellikle, bir BrainFuck yorumlayıcısı, banttaki hücrelerin sayısı ile ilgili zor bir sınırlamaya sahip olması nedeniyle kusurludur, ancak bazı tercümanlar hücreleri dinamik olarak ekler. Bunlar, tüketilene kadar bellek tüketmeye devam edecektir.

beefBu tür bir tercümandır ve Ubuntu Yazılım Merkezinde bulunmaktadır ve kullanılmayan bir makinedeki mevcut çalışmam 29 saat önce başladı ve o zaman 1GB RAM kullandı. İşte çıktısı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 önbellek ve 6 GB takas alanı vardır, bu yüzden sanırım bu cevabı yaklaşık 12 gün içinde nasıl gittiğini güncelleyeceğim.

GÜNCELLEME 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    

GÜNCELLEME 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   

Demek 10 gündür çalışıyor. İlginç bir şey olmadan önce en az 10 kişi daha çalışacak gibi görünüyor.


Güzel ve kısa.
nrubin29

15

C ve POSIX

Burada çok taşınabilir bir çözümü hedefliyorum. Sorun, saf C'nin İşletim Sistemine, program kapandıktan sonra belleğin ayrılmış kalması gerektiğini söyleme yönteminin olmadığı görünüyor. Bu yüzden POSIX kullanmam için kendime izin veriyorum; Çoğu işletim sistemi Windows, Linux ve MacOS X dahil olmak üzere POSIX uyumluluğu konusunda bazı hak taleplerine sahiptir. Ancak, yalnızca Ubuntu 12.04 32bit'te test ettim. Süper kullanıcı izinleri gerektirmez.

Bu çözüm aslında geleneksel while(1){malloc(1);}çözümdür. Ancak malloc yerine POSIX paylaşılan bellek işlevlerini kullanır. Her tahsise paylaşılan bir bellek tanımlayıcısı atadığı için, işlem sona erdiğinde belleğe erişmek hala mümkündür. Böylece çekirdek hafızayı serbest bırakamaz.

#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*/
  }
}

En iyi ve en parlak C cevap IMO. +1
syb0rg

1
Güzel. Karşılaştığım ilk çözüm Andrew Medico idi, ancak bu Linux'ta mümkün değildi ve Windows programlamayı sevmediğim için, paylaşılan hafızadan sızmak istedim, ancak POSIX işlev isimlerini hatırlayamadım. Beni hatırladığın için teşekkürler;) Bulduğum tek şey sadece işlem sonlandırmasında eşlenmemiş mmap şeylerdi ...
foobar

14

C #

İşleyici kapsam dışına çıkmadan önce olaylardan çıkmak istediğinizi unutmak, .NET'in OutOfMemoryException'ı atana kadar bellek sızdırmasına neden olur.

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

Açıklama : whileDöngünün içine, çerçevenin daha fazla bellek tahsis etmesine neden olan yeni bir nesne inşa ederiz, ancak Bfarklı bir sınıftaki bir olaya bir örnek yöntemi atayarak, kapsam dışında olduğunda yeni örneğin serbest bırakılmasını da önleriz, Sonuç, yeni Börneğimizin kodumuzdan erişilemez hale gelmesi, ancak bir başvuru hala var, bu da GC'nin akapsam dışında kalana kadar serbest bırakmayacağı anlamına geliyor .

Statik olaylar, aynı kapsamdadır, çünkü asla kapsam dışına çıkmazlar, ilk önce olayın aboneliğinden çıkmadığınız sürece, yalnızca süreç sona erdiğinde temizlenirler. Referanslarınızı daima saklayın, millet!

using System;

class Program
{
    static event Action Event;

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

Yukarıdakiler aynı fikir üzerinde çalışır, whiledöngü kapsam dışına çıktığında işleyiciye erişilemez hale gelir , bu durumda olayın aboneliğini iptal etmeyi imkansız hale getirir, böylece program sona erene kadar hafızanın orada oturacağı anlamına gelir. Statik olaylar, örnek olaylara göre daha tehlikelidir, çünkü asla kapsam dışına çıkmadıklarından emin olabilirsiniz.

DÜZENLE : Aynı zamanda, bir referans eklediğiniz sürece, aynı zamanda bu referansı serbest bırakmanın bir yolu olmadığından, temelde başka herhangi bir nesneyle de yapabilirsiniz.

İşte statik nesneler ve diziler kullanan bir örnek.

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

Diziler listeye eklenmeye devam eder, ancak kodu değiştirmeden listeyi temizlemenin bir yolu yoktur; bu, kapalı kaynaklı uygulamalar için imkansızdır. Geçirilen sayının artırılması, Leak.Adddaha hızlı sızmasına neden olur, eğer yeterince yüksek ayarlarsanız, sadece bir OverflowException'ın atılmasına neden olur.


10

bash (harici yardımcı program yok)

Burada çatal bomba yok.

Uyarı: Kabuğunu öldürebilir.

Referans için bir tam sayı dizisi oluşturmaya çalışıyorum çünkü tam sayıların nasıl göründüğünü unutmaya devam ediyorum.

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

Sonuçlar:

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

2
+1 için "çünkü tam sayıların nasıl göründüğünü unutmaya devam ediyorum" :)
David Conrad

8

J (7)

UYARI: Bu çalıştığımda sistemimi dondu (qt terminalinde Windows 8, J 8.01).

2#^:_[_
  • 2# Her bir öğeyi çoğaltarak argümanın uzunluğunu iki katına çıkarır,
  • ^:_ Verilen işlevin fikrini bulur (fakat hiçbiri sonsuz döngü yapmaz)
  • [__argüman olarak çağırır .

8

Haskell (Graham'ın numarası)

Çok basit: bu Graham'ın sayısını hesaplar

Buradaki diğer örneklerin aksine, sonsuza dek sürmeyecek ... çok fazla cpu kullanacak, ancak teorik olarak sonlandırabilir. eğer numarayı saklamak gerçek olmasaydı ...

gözlemlenebilir evren, her bir rakamın bir Planck hacminde olduğunu varsayarsak, Graham sayısının sıradan bir dijital gösterimini içermek için çok küçük .

(wikipedia'ya göre)

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

Bu nedenle, fikir, hafızanın (giderek artan bir şekilde) muazzam Integer(lar) tarafından kullanılacağıdır (Haskell'in Tamları isteğe bağlı boyuttadır).

Test etmek istiyorsanız yığın boyutunu arttırmanız veya içine yerleştirmeniz gerekebilir ghci.


2
Aptal evren, Integers için Haskell standardına uymuyor. Neden rastgele boyutu desteklemiyor?
PyRulez

6

@ Comintern tarafından ilham alındı.

/ Dev / null komutunun değiştirilmesi. Sinsi modu devreye sokmak. Çekirdek başlıkları, süper kullanıcı modu ve çalışan bir derleyici gerektirir.

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

İyi eğlenceler.

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

Kaynak kodu:

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

Bu uyarı sizi yeniden başlatmaya zorlayabilir!

Kaldırmak için:

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

6

Yakut

Herkes bu toplamı bilir (1 / n ^ 2) = pi ^ 2/6

Böylece bir yaklaşım fonksiyonunu tanımlayabilirim:

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

p pi_approx.(100_000)

Tabii ki (1..infinity) vahşileşecek.

Ancak tembel kullanmanın bu işi yapacağına dikkat edin;)

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 karakter (tam program)

Bunu çalıştırmayın, yoksa sisteminiz çabucak donar!

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

Malloc'a yapılan çağrı 9 byte'lık bir hafıza ayırır ve işletim sisteminden düzenli olarak yeni bellek sayfaları ister. Malloc tarafından ayrılan hafıza, iade edilen adrese hiçbir işaretçi kaydedilmediği için hemen sızdırılır. Sistemin belleği tükendiğinde (RAM ve takas alanı) veya işlem için bellek sınırına ulaşıldığında, program döngü sırasında kesilir ve sonlanır.


2
Çok uzun sürmez - herhangi bir makul modern sistem , süreci başlatan ve öldüren bir OOM katiline sahip olmalıdır . En azından 12.04 Ubuntu yapar.
Dijital Travma

1
Eh, bu kodu çalışırken Ubuntu 13.10'umu
çarptım

@DigitalTrauma Örneğin FreeBSD'de bir OOMK var mı?
Ruslan

1
main(){while(malloc(9));}3 karakter daha kaydeder ve hafızamı hemen anında doldurur.
gmatht

@gmatht: Öneri için teşekkürler! Cevabı değiştirdim ... her bloğun blok boyutunu arttırma fikrini sevdim.
Mathieu Rodic

4

VBScript

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

Kendisine işaret eden bir sözlük yaratıyoruz. Sonra sözlüğü Yoktan ayarlayarak imha ettiğimizi düşünüyoruz. Ancak, geçerli bir (dairesel) başvuru olduğundan sözlük hala bellekte var.

Döngü, aynı zamanda bellek domuz, programın askıda kalmasına neden olur. Programı kapattıktan sonra, hafıza hala kullanımda. Sistem ancak yeniden başlatılarak geri yüklenebilir.


Gerçekten mi? VBScript sadece başlık altında VB.NET kullanmaz? Dairesel referanslar normalde, basit referans sayma uygulamaları hariç, çöp toplayıcıları için sorun değildir ve programın sonlandırılması tüm yığınının serbest bırakılmasıyla sonuçlanmalıdır , değil mi?
David Conrad

@DavidConrad Öyle düşünürdünüz, ancak bunu her araştırdığımda ve bu tür komut dosyalarını çalıştırdığımda makinemi yeniden başlatmam gerekiyordu.
AutomatedChaos

1
VBScript, VB.Net'i önemli ölçüde önceden gösterir - VB.Net'in komut satırı sürümü değildir; Bu eski Visual Basic'ın yorumlanmış bir altkümesidir.
Chris J,

İkinizide tesekkurler. VBScript ve VB.NET arasındaki ilişkinin ne olduğunu anlamadım.
David Conrad

4

Evet & tmpfs

Ubuntu ile ücretsiz olarak geldiğinde neden yeni bir program yaz?

yes > /run/user/$UID/large_file_on_my_ramdisk

Muhtemelen bildiğiniz ya da tahmin ettiğiniz gibi, Ubuntu / run / user / 'ı varsayılan olarak bir RAM diski olan bir tmpfs olarak bağlar .

Kapatmana bile gerek yok. Kibar bir şekilde kendisini kapatacak ve güzel bir bellek parçası bırakacak. Sanırım, yesbaşka bir şey aramayan tek iş parçacıklı, tek işlemli bir program olduğunu düşünüyorum (mevcut bir RAM diskine yazmak, aynı zamanda tercih ettiğiniz dile taşınabilir).

Küçük bir hatası var: Ubuntu, kullanıcının yazılabilir tmpfs / run / 1000 ila 100 MB’yı varsayılan olarak sınırlandırdığından, takas ölümü özelliği makinenizde kullanılmayabilir. Ancak bunu makinemde aşağıdaki hızlı çözümle düzeltmeyi başardım:

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

Hiç bir /run/userrehberim yok . Hangi Ubuntu sürümünü kullanıyorsunuz ve bunun için ne yüklediniz?
Ruslan,

Ubuntu Güvenilir Tahr (14.04). Özel bir kurulum gerekmez.
gmatht

tmpfsMonte edilmiş bir dosya sisteminizin olup olmadığını bulmak için bunları birlikte listeleyebilirsiniz df -t tmpfs. Benim Ubuntu sistemimde çok hoş bir /run/shm...
Toby Speight

4

darbe

Uyarı: Aşağıdaki kod, bilgisayarınızın ön yüklenememesini sağlar.

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

Uyarı: Yukarıdaki kod, bilgisayarınızın ön yüklenememesini sağlar.

/ Dev / sda'yı boot sürücünüzle değiştirin. Bu, E8 FD FF'yi açılış sektörünüzün başlangıcına yazar. Önyükleme yaparken, BIOS önyükleme sektörünüzü belleğe okur ve yürütür. Bu kodlar bu düzeneğe eşdeğerdir:

label:
  call label

Bu sonsuz bir tekrarlamadır ve sonunda yığın taşmasına neden olur.


Derleme örneğinizde, jmpcall
15

çağrısı, geri dönüş adresini istifte ret için bırakır. sıçramak yığın taşmasına neden olmaz.
Jerry Jeremiah

3

Haskell

main=print $ sum [0..]

Bu sayma sayıları toplamaya çalışır. Haskell kısmi toplamları değerlendiriyor, sadece sonsuz bir ekleme ifadesi haline geliyor. Derleyiciyi optimizasyon bayraklarıyla çalıştırırsanız, çalışmayabilir.


3

darbe

Özellikle bellek tüketmek için tasarlanmamış yardımcı programları kullanabildiğimiz için, belleği boşaltmak için bir yardımcı programa odaklanıyorum: swapon . Bu, çekirdeğin diske yazarak belleği boşaltmasına izin vermek için kullanılır.

Bu komut dosyası iki optimizasyon gerçekleştirir: (1) / tmp'ı daha hızlı yapmak için tmpfs (bir tür RAM diski) olarak tmpfs takma ve (2) belleği boşaltmak için bir takas dosyası oluşturma. Bunların her biri kendileri tarafından makul görünse de, dikkatsiz bir kullanıcı her ikisini de yaparsa, bir takas döngüsünü başlatır: işletim sistemi sayfaları takas etmeye çalıştığında, tmpfs'e yazar; bu, tmpf'lerin daha fazla bellek kullanmasını sağlar; bu, daha fazla sayfanın değiştirilmesine neden olarak bellek basıncını arttırır. Bu benim VM'mde birkaç dakika sürebilir, sistemin kendisini kullanarak bir çukur kazmasını izlemeniz için çok zaman alır top.

Programın kapatılması çok az fark yaratır, çünkü programın kendisi neredeyse hiç hafıza ayırmaz. Aslında, boş hafıza kullanımı önemsiz değildir, çünkü swapofftakas alanından önce tmpfs'leri sökerek hafızayı boşaltamazsınız ve bu hafıza boşa çıkıncaya kadar yapmak zordur.

Bu cevap, ağdan serin hileler uygulayarak onları anlamadan körlemeye karşı uyarıcı bir masal olarak düşünülebilir.

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

Dairesel referanslar kullanır. Değişkenler için referans sayısı hiçbir zaman 0'a ulaşmaz ve referanslar hiçbir zaman çöp toplanmaz.

Sabırlı olmanız gerekebilir, ancak sisteminizi boğmanız garanti edilir. Disk daha hızlı dönmeye başlar ve duman görülebilir olabilir.


2

PHP (yalnızca linux):

Bu kod denenmemiş, çünkü php çalışan bir linux bilgisayarım yok.

Ama bu benim kavram kanıtımdır:

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

Bu, belleği büyük RGBA görüntüleri (10000x10000 piksel) ile doldurur.

Bu bebeği kapatmanın tek yolu gücü kapatmak.

Kodun tümü yorumlandı.

Herhangi bir gelişme, şüphe, hata veya herhangi bir şey, aşağıdaki yorum kutusunu kullanın.


Linux aklına erişimi olan herhangi biri test ediyor mu? Thanks :)
George

Linux'um var, nasıl çalışacağından emin değilim. 1 cevabı için baskı ekranını sağladım, ancak bu köpek yavrusu linux'un gerçekten eski bir versiyonu. Ubuntu php çalıştırmak için çok yavaş. Belki daha sonra Android'imde test ederim.
Ismael Miguel

1
başka bir programın çağrılmaması noktasında başarısız olur
Einacio

Başka bir program çağırmıyor: aynı dosya için dosyayı başlatan aynı programı çağırıyor.
Ismael Miguel,

2

Python - 56

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

Bir sınıf oluşturur, nitelikleri ayarlamak için bir yöntem tanımlar, içerisinde bir nitelik belirler ve daha sonra bir niteliği ayarlamaya çalıştığı bir ilk örnek oluşturur.

Basit bir özyinelemeli işlev ( def f(x):f(x)) biraz yaratıcı değildi gibi görünüyordu, bu yüzden asla aramaya karar verdim bir işlevi .

Bellek yönetimi özyineleme derinliğini yakalayabilir, ancak bu gerçekten uygulamaya bağlıdır.

Bu bir çatal bomba ise, lütfen söyle.


4
Bu, sadece bir hafıza yorgunluk neden olur: RuntimeError: maximum recursion depth exceeded while calling a Python object. Maksimum özyineleme sınırını sys.setrecursionlimitneredeyse hiç bellek olmadan ayarlamak bile bir segmentasyon hatası ile çökmeden önce kullanılır.
Bakuriu

@Bakuriu Dediğim gibi, gerçekten uygulamaya bağlı (Python'un C'ye (++) dönüşen ve derleyen, örneğin Shedskin, Nuitka gibi uygulamaları var).
cjfaure

2
Ardından, kodu hangi uygulamalara / uygulamalara yazdığınızı belirtin. Yalnızca sözdiziminin önemli olduğu ve bu nedenle uygulamanın ilgili olmadığı zorluklar ile tamamen dilin nasıl uygulandığına bağlı olan zorluklar arasında bir fark vardır.
Bakuriu

2

Perl

Çok basit bir şey ama golf oynamak gibi hissettim.

{$x=[$x];redo}

İki yinelemeden sonra, $xdiziyi içeren bir başvuru içeren diziye bir başvuru içerir.undef .

Bellek kullanımı zaman içinde doğrusaldır, küçük tahsislerle, ancak Ubuntu Linux sistemimde pencere yöneticimi ciddi şekilde yavaşlatmak sadece birkaç saniye sürdü. Yarım dakika sonra OOM katili bununla ilgilendi.


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

Not: Bu kullanır setTimeoutparçası olarak tanımlanan, Zamanlayıcılar - HTML Yaşam Standardı .

Mozilla Firefox'ta deneyin (geliştirici konsoluna yapıştırabilirsiniz). Firefox giderek daha fazla hafıza tüketmeye devam ediyor ve100% ve CPU'yu tek çekirdekli bir makinede kullanıyor (benimki gibi 25%CPU'yu kullanan 4 çekirdekli bir makinede ). Ayrıca, durduramayacağınız ilave bir faydası da vardır; Görev yöneticisini açabilirseniz, Firefox'u onunla öldürebilirsiniz.


1
Bir çekirdeğin% 100'ünü kullanır. Quadcore işlemcinizde CPU kullanımı% 25 ile sonuçlanır.
Iván Pérez

@Electrosa Evet, kesinlikle haklısın. Cevabımı güncelledim.
Diş fırçası

Bu bir kod golf sorusu değil, lütfen kodunuzu okunabilir hale getirmeye çalışın.
Paŭlo Ebermann

@ PaŭloEbermann Tamam. Ungolfed versiyonunu gönderdim.
Diş fırçası

1

darbe

Boş bir dosya oluşturun Bu metin dosyasıyla test
değiştirin/dev/null/

$ sudo mv test /dev/null

Bu @ Comintern'in cevabına benzer şekilde çalışır. /dev/nullŞimdi tüm çıktılar , zaman içinde devasa ve sistemi çökertecek olan bu metin dosyasına eklenecektir.


1
Çok büyük bir dosya sistemi çökertmez. Ve ortalama 500 gb boyutunda bir disk büyüklüğü varsayarsak, diskin doldurulması bile biraz zaman alabilir.
w4wetewtwetwet

1
Sistemlerde /devbir olduğunu devtmpfs, bu doldurup sistemini engelleyebilir. Sanırım bu cevabın amacı bu.
Toby Speight

1

Bash: 7 karakter

Bu en basit bash çözümü olmalı. Çatal yok, hile yok.

x=`yes`

Bunu root olarak çalıştırmamanız tavsiye edilir.


Ek not: bunu yarıda ctrl-c ile ve sonra unsetdeğişkenle sonlandırsanız bile , kabuk öldürülene kadar bellek ayrılmış kalır. Katliamı içeride izleyebilirsiniz top.
Riot

Bash 4.2.45 (1) ile yaptığım kendi testleri unset x, belleği boşalttığını gösteriyor . pdksh de belleği boşaltır, ancak ksh93 serbest exitbırakmaz ve ksh93'te çekirdek çeker.
kernigh

Benim için (bash 4.3.11 (1)), ana kabuk için yerleşik hafıza ekranı yes, öldürülene kadar durmadan tırmanıyor , bu noktada orada kalıyor ve unsetetkisiz kalıyor . Ancak bu büyük bir bellek sisteminde ve birkaç gigabayttan oluşan bir değişkene sahip olmak onu rahatsız etmiyor gibi görünüyor (en sonunda kabuğu öldürmeye karar verene kadar).
Riot

0

C

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

Sayfadan sonra hafıza sayfasını alır ve sonunda hiç hafıza kalmadı.


Bir sayfa 4 KB olan ne kadar evrenseldir?
Peter Mortensen,

@Peter 4K genellikle boyuttadır, ancak gerçekten evrensel olup olmadığını söyleyemem, ancak sayfa boyutunun verilen soru ile hiçbir ilişkisi yoktur.
ST3

1
@ ST3: Bellek sayfasını kirletmelisiniz. Çoğu modern işletim sistemi sanal bellek kullanır ve yalnızca bellek ayırdığınızda sanal bellek tablosunda kayıt yapar. Bellek sayfasına tek bir bayt yazmak, işletim sistemini zaten sanal bellek sayfasını fiziksel belleğe eşlemeye zorlar.
foobar


0

Yakut

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

Sadece sonsuzca özyinelemeli (özyinelemeli!) Kendine referanslar ekler.

Birisi onunla Ruby kum havuzumu kırdığında bu küçük gem hakkında öğrendim . : D

Özyinelemeli yönlerinin demosu:

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

Sigara golfed

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

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

Girişimi, ana telefondan çağrı eklemek için düzelttim.


Bu bir popülerlik yarışması. Program çalışıyorsa, ana ve başlığı tutun. bu iyi. Ayrıca, golf oynamayan bir sürüm yayınlayabilir misiniz? Thanks :)
George
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.