Ваша задача - написать код, который будет пропускать как минимум один байт памяти за как можно меньшее количество байт. Память должна быть просочилась, а не просто распределена .
Утечка памяти - это память, которую программа выделяет, но теряет возможность доступа до того, как она сможет правильно освободить память. Для большинства языков высокого уровня эта память должна быть выделена в куче.
Примером на C ++ будет следующая программа:
int main(){new int;}
Это делает new int
в куче без указателя на него. Эта память мгновенно просочилась, потому что у нас нет возможности получить к ней доступ.
Вот как может выглядеть сводка утечек из Valgrind :
LEAK SUMMARY:
definitely lost: 4 bytes in 1 blocks
indirectly lost: 0 bytes in 0 blocks
possibly lost: 0 bytes in 0 blocks
still reachable: 0 bytes in 0 blocks
suppressed: 0 bytes in 0 blocks
Во многих языках есть отладчик памяти (например, Valgrind ), если вы можете, вы должны включить вывод такого отладчика, чтобы убедиться, что у вас есть утечка памяти.
Цель состоит в том, чтобы минимизировать количество байтов в вашем источнике.
Ответы:
Perl (5.22.2), 0 байт
Попробуйте онлайн!
Я знал, что там будет какой-то язык, который пропустит память в пустой программе. Я ожидал, что это будет esolang, но оказывается, что
perl
утечка памяти в любой программе. (Я предполагаю, что это преднамеренно, потому что освобождение памяти, если вы знаете, что в любом случае собираетесь выйти, просто тратит время; поэтому общая рекомендация в настоящее время состоит в том, чтобы просто утечка оставшейся памяти, когда вы находитесь в процедурах выхода вашей программы .)верификация
источник
perl --version
на своей машине Несмотря на то, что он никогда не запускает какую-либо программу.C
48 3122 байтаПредупреждение: не запускайте это слишком много раз.
Спасибо Деннису за помощь и идеи!
Это идет на шаг дальше.
shmget
выделяет разделяемую память, которая не освобождается при завершении программы Он использует ключ для идентификации памяти, поэтому мы используем неинициализированный int. Это технически неопределенное поведение, но практически это означает, что мы используем значение, которое находится чуть выше вершины стека, когда это вызывается. Это будет записано в следующий раз, когда что-либо будет добавлено в стек, поэтому мы потеряем ключ.Единственный случай, когда это не работает, это если вы можете выяснить, что было в стеке раньше. Для дополнительных 19 байтов вы можете избежать этой проблемы:
Или для 26 байтов:
Но с этим, утечка памяти после выхода из программы. Во время работы программа имеет доступ к памяти, что противоречит правилам, но после завершения программы мы теряем доступ к ключу, и память все еще выделяется. Это требует рандомизации макета адресного пространства (ASLR), иначе
&k
всегда будет одинаковым. В настоящее время ASLR обычно включен по умолчанию.Проверка:
Вы можете использовать,
ipcs -m
чтобы увидеть, какая разделяемая память существует в вашей системе. Я удалил ранее существующие записи для ясности:источник
Unlambda (
c-refcnt/unlambda
), 1 байтПопробуйте онлайн!
Это действительно сложная задача - найти уже существующий интерпретатор, который теряет память на очень простых программах. В этом случае я использовал Unlambda. Существует более одного официального интерпретатора Unlambda, но он
c-refcnt
является одним из самых простых в сборке, и у него есть полезное свойство, заключающееся в утечке памяти при успешной работе программы. Таким образом, все, что мне нужно было дать, - это простейшая из возможных легальных программ Unlambda, неактивная. (Обратите внимание, что пустая программа здесь не работает; память все еще доступна в момент сбоя интерпретатора.)верификация
источник
TI-Basic, 12 байт
«... утечка памяти - это то, где вы используете Goto / Lbl в цикле или если условно (все, что имеет команду End), чтобы выпрыгнуть из этой структуры управления до того, как будет достигнута команда End ...» (подробнее)
источник
Pause
в конце? Вы можете сэкономить 2 байта.Python <3.6.5, 23 байта
property.__init__
Утечки ссылки на имущество СТАРЫЙfget
,fset
,fdel
и__doc__
если вы называете его на уже инициализированproperty
инстанции. Это ошибка, которая в конечном итоге сообщается как часть проблемы CPython 31787 и исправлена в Python 3.6.5 и Python 3.7.0 . (Кроме того, да,property([])
это то, что вы можете сделать.)источник
C #, 34 байта
Это решение не требует кучи. Ему просто нужен действительно трудолюбивый GC ( сборщик мусора ).
По сути это превращает GC в своего собственного врага.
объяснение
Всякий раз, когда вызывается деструктор , он создает новые экземпляры этого злого класса, пока истекает время ожидания, и говорит GC просто отбросить этот объект, не дожидаясь завершения деструктора. К тому времени были созданы тысячи новых экземпляров.
«Зло» в том, что чем сильнее работает GC, тем больше это взорвется вам в лицо.
Отказ от ответственности : ваш сборщик мусора может быть умнее моего. Другие обстоятельства в программе могут привести к тому, что GC проигнорирует первый объект или его деструктор. В этих случаях это не взорвется. Но во многих вариациях так и будет . Добавление нескольких байтов здесь и там может обеспечить утечку при любых возможных обстоятельствах. Ну, кроме выключателя питания, может быть.
Контрольная работа
Вот тест люкс :
Выход через 10 минут:
Это 2 684 476 624 байта. Общий
WorkingSet
объем процесса составил около 4,8 ГБЭтот ответ был вдохновлен замечательной статьей Эрика Липперта: « Когда все, что ты знаешь, неправильно» .
источник
class L{~L(){new L();}}
? AFAIKfor(;;)
только делает утечку памяти быстрее, верно?C (gcc) , 15 байтов
верификация
источник
Javascript, 14 байт
Golfed
Регистрирует пустой обработчик интервала с задержкой по умолчанию, отбрасывая итоговый идентификатор таймера (делая невозможным отмену).
Я использовал интервал не по умолчанию, чтобы создать несколько миллионов таймеров, чтобы проиллюстрировать утечку, так как при использовании интервала по умолчанию процессор расходуется как сумашедший.
источник
if(window && window.setInterval && typeof window.setInterval === 'function') { window.setInterval(0); }
clearInterval
с возрастающим идентификатором, пока ваш интервал не истечет. Например:for(let i=0;i<1e5;i++){try{clearInterval(i);}catch(ex){}}
free()
Java, 10 байт
Наконец, конкурентный ответ на Java!
Golfed
Это ссылка на метод (против строковой константы), которую можно использовать так:
Литеральная строка
". "
будет автоматически добавлена в глобальный пул интернированных строк, поддерживаемыйjava.lang.String
классом, и, как только мы немедленно обрежем ее, ссылка на нее не может быть повторно использована в коде (если вы снова не объявите точно такую же строку).https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#intern--
Вы можете превратить это в утечку памяти «производственного уровня», добавив строку к себе, а затем явно вызвав метод intern () в цикле.
источник
("." + " ").intern()
будет делать (если бы они были введены пользователем или без, поэтому мы не учитываем оптимизацию компилятора).simply by guessing it correctly
, но это не означает, что такой вещи, как утечки памяти, не существует.there's probably some way to use reflection to determine the string's contents too
не могли бы вы продемонстрировать это? (подсказка, String.intern () реализован в собственном коде).Ржавчина, 52 байта
Выделяет несколько байтов системе malloc. Это предполагает, что неправильный ABI приемлем.
Ржавчина (теоретически), 38 байтМы выделяем память в куче, извлекаем необработанный указатель, а затем просто игнорируем его, эффективно вытекая из него. (
Box::into_raw
тогда корочеstd::mem::forget
).Тем не менее, Rust по умолчанию использует jemalloc, который valgrind не может обнаружить утечки . Мы могли бы переключиться на системный распределитель, но это добавляет 50 байтов и требует каждую ночь. Большое спасибо за безопасность памяти.
Выход первой программы:
источник
8086 ASM, 3 байта
В этом примере предполагается, что среда выполнения C связана с.
это собирает туда,
e9 XX XX
гдеXX XX
это относительный адрес_malloc
Это вызывает
malloc
выделение непредсказуемого объема памяти, а затем немедленно возвращается, завершая процессы. В некоторых операционных системах, таких как DOS, память может вообще не восстанавливаться, пока система не будет перезагружена!источник
Далее 6 байт
Golfed
Выделяет пустую строку с
s" "
, оставляя ее адрес и длину (0) в стеке, затем умножает их (что приводит к потере адреса памяти).Valgrind
источник
идти 45 байтов
это создает анонимную программу с бесконечным циклом внутри нее. программа может продолжать работать в обычном режиме, так как запуск программы походит на порождение одновременно запущенного небольшого потока, но программа не имеет возможности вернуть память, выделенную для программы. сборщик мусора никогда не соберет его, так как он все еще работает. некоторые люди называют это «утечка горутин»
источник
C.malloc(8)
, так как вам нужноimport"C"
Java 1.3, 23 байта
Создание потока, но не запуск его. Поток зарегистрирован во внутреннем пуле потоков, но никогда не будет запущен, поэтому никогда не заканчивается и поэтому никогда не будет кандидатом в GC. Это невосстановимый объект, застрявший в лимбе Java.
Это ошибка в Java до версии 1.3, так как она была исправлена позже.
тестирование
Следующая программа гарантирует загрязнение памяти новыми объектами потока и показывает уменьшение свободного места в памяти. Ради тестирования утечек я интенсивно заставляю GC работать.
источник
Befunge ( грибки ), 1 байт
Это может зависеть от платформы и версии (я тестировал только с версией 1.0.4 для Windows), но грибы исторически были очень утечкой. Команда
$
(drop) не должна ничего делать в пустом стеке, но зацикливание на этом коде каким-то образом приводит к очень быстрой утечке большой памяти. В течение нескольких секунд он израсходует пару концертов и вылетит с ошибкой «недостаточно памяти».Обратите внимание, что это не обязательно должна быть
$
команда - почти все, что подойдет. Это не будет работать с пустым исходным файлом, хотя. Там должна быть хотя бы одна операция.источник
Swift 3, 38 байт
Новая версия:
x
имеет сильную ссылку на себя, поэтому он не будет освобожден, что приведет к утечке памяти.Старая версия:
x
содержит сильную ссылку наy
, и наоборот. Таким образом, ни один из них не будет освобожден, что приведет к утечке памяти.источник
x
иy
, таким образом, это не выглядит для меня утечкой (если вы не уничтожите их как-нибудь).do
блоке, который бы исправил проблему, вызванную цеппелином, верно?do
будет работать так же. Хорошая идея!class X{var x: X!};do{let x=X();x.x=x}
Delphi (Object Pascal) - 33 байта
Создание объекта без переменной, полная консольная программа:
Включение FastMM4 в проекте покажет утечку памяти:
источник
C # - 84 байта
Это выделяет ровно 1 байт неуправляемой памяти, а затем теряет то
IntPtr
, что, я считаю, является единственным способом получить или освободить его. Вы можете проверить это, поместив его в цикл и ожидая сбоя приложения (может потребоваться добавить несколько нулей, чтобы ускорить процесс).Я считал
System.IO.File.Create("a");
и такое, но я не уверен, что это обязательно утечки памяти, так как само приложение будет собирать память, под ней может просочиться ОС (потому чтоClose
илиDispose
не были вызваны). Для доступа к файлу также требуются разрешения файловой системы, и никто не хочет на них полагаться. И оказывается, что в любом случае это не произойдет, потому что ничто не мешает вызову финализатора (который делает возможным освобождение базовых ресурсов), что включает в себя структура, чтобы смягчить подобные ошибки (в некоторой степени), и путать программистов с, казалось бы, недетерминированной блокировкой файлов (если вы циник). Спасибо Джону Ханне за то, что объяснил мне это.Я немного разочарован тем, что не могу найти более короткий путь. .NET GC работает, я не могу вспомнить ни одного
IDisposables
в mscorlib, который точно утечет (и, действительно, все они, похоже, имеют финализаторы, как это раздражает) , я не знаю ни одного другого способа выделения неуправляемой памяти (если не считать PInvoke ), а отражение гарантирует, что может быть найдено что-либо со ссылкой на него (независимо от семантики языка (например, частные члены или классы без методов доступа)) .источник
System.IO.File.Create("a")
не будет ничего пропускать, ноGC.SuppressFinalize(System.IO.File.Create("a"))
будет, как явно просят, не запускать финализаторFileStream
произведенного.<!-- language: lang-c# -->
Спасибо за это и хороший ответ! (Это C #, так что я люблю его)Фактор , 13 байт
Factor имеет автоматическое управление памятью, но также предоставляет доступ к некоторым функциям libc:
Вручную выделяет 1 байт памяти, возвращает его адрес и удаляет его.
malloc
на самом деле регистрирует копию для отслеживания утечек памяти и двойного освобождения, но выявление того, что вы обнаружили, не простая задача.Если вы предпочитаете убедиться, что действительно потеряли эту ссылку:
Тестирование утечек
[ 1 malloc drop ] leaks.
говорит:Тестирование утечек
[ 1 (malloc) drop ] leaks.
говорит:о нет! Плохой фактор, теперь у него болезнь Альцгеймера! D:
источник
AutoIt , 39 байт
Выделяет один байт из кучи. Так как дескриптор, возвращаемый
_MemGlobalAlloc
функцией, отбрасывается, нет никакого способа явно освободить это распределение.источник
Common Lisp (только SBCL),
2826 байтВы запустите его так:
sbcl --eval 'sb-alien::(make-alien int)'
; ничего не печатается и не возвращается, но происходит выделение памяти. Если я оберну форму внутри(print ...)
, указатель отобразится в REPL.package::(form)
это специальная запись в SBCL для временного связывания текущего пакета при чтении формы. Это используется здесь, чтобы избежать префиксов какmake-alien
иint
сsb-alien
. Я думаю, что было бы обманом предполагать, что текущий пакет установлен на этот, потому что это не так при запуске.make-alien
выделяет память для заданного типа и необязательного размера (используя malloc).При выполнении этого в REPL добавьте
0
после распределения, чтобы REPL не возвращал указатель, а вместо этого значение. В противном случае не, что бы не быть реальной утечкой , потому что РЕПЛИ запоминает последние три возвращаемых значений (см*
,**
,***
) , и мы могли бы все еще есть шанс , чтобы освободить выделенную память.2 байта удалены благодаря PrzemysławP, спасибо!
источник
1
(или2
,3
и т. Д.) Вместо того,()
чтобы вернуть значение1
? Это спасло бы 1 байт. И этот ответ только REPL? Может быть, если вы загрузите код, которыйload
вы не можете включить()
или что-то в конце, потому что он не будет доступен в любом случае?eval
и это работает, как вы сказали. Большое спасибо!C ++, 16 байт
У меня нет valgrind, чтобы проверить, нет ли утечек, но я уверен, что так и должно быть.В противном случае я бы попробовал:Результат Valgrind
(Это действительно утечка)
источник
g++ 4.3.2
(не самый последний), и он прекрасно компилируется.int
Думаю, по умолчанию нет возвращаемого типа . При этом у-Wall
меня есть предупреждение, хотя:plop.cpp:1: warning: ISO C++ forbids declaration of 'main' with no type
[]{new int;}
функцией C ++ (в задаче не указана целая программа).Java (OpenJDK 9) ,
322220 байтПопробуйте онлайн!
Это другая утечка памяти, которая не использует String Cache. Он выделяет половину вашей оперативной памяти, и вы не можете ничего с этим поделать.
Спасибо zeppelin за сохранение всех байтов
источник
Unsafe
экземпляр из статической переменной внутри него, как то:import sun.misc.*;class M{static void main(String[]a)throws Exception{java.lang.reflect.Field f=Unsafe.class.getDeclaredField("theUnsafe");f.setAccessible(1<2);((Unsafe)f.get(1)).allocateMemory(1);}}
public static void main
статический инициализаторstatic{try{}catch(Exception e){}}
(который может быть немного сложнее в запуске, но, тем не менее, допустим и компилируем).a
вместо нихargs
и удалите публичные. tio.run/nexus/…с, 9 байтов
Доказательство:
источник
gcc
является. Это также должно работать с пустой программой. Попробуйтеgcc src.c && valgrind ./a.out
, что должно привести к чистому результату.C #, 109 байт
Мы нашли идею, лежащую в основе этой утечки, в рабочем коде, и ее исследование ведет к этой статье Основная проблема в этой длинной цитате из статьи (читайте ее для получения дополнительной информации):
Запуск из компилятора в Visual Studio 2015 и использование окна инструментов диагностики показывает следующие результаты примерно через 38 секунд. Обратите внимание, что объем памяти процесса постоянно растет, а сборщик мусора (GC) продолжает работать, но ничего не может собрать.
источник
C 30 байтов
Valgrind Результаты:
источник
main(){malloc(1);}
?Дротик, 76 байт
Немного похоже на ответ JavaScript. Когда вы вызываете
.listen
объект потока Dart, вам возвращается подписка StreamSubscription, которая позволяет вам отключиться от потока. Однако, если вы выбросите это, вы никогда не сможете отписаться от потока, что приведет к утечке. Единственный способ устранить утечку - это если сам поток получен, но на него все еще ссылается внутренняя комбинация StreamController + Timer.К сожалению, Дарт слишком умен для других вещей, которые я пробовал.
()async=>await new Completer().future
не работает, потому что использование await - это то же самоеnew Completer().future.then(<continuation>)
, что и использование, которое позволяет уничтожить само замыкание, если второй Completer не указан (Completer содержит ссылку на Future из.future
, а Future содержит ссылку на продолжение как замыкание).Кроме того, изоляты (то есть потоки) очищаются с помощью GC, поэтому создание нового потока и немедленная его приостановка (
import'dart:isolate';main(_)=>Isolate.spawn(main,0,paused:true);
) не работает. Даже создание Isolate с бесконечным циклом (import'dart:isolate';f(_){while(true){print('x');}}main()=>Isolate.spawn(f,0);
) убивает Isolate и выходит из программы.Ну что ж.
источник
Swift, 12 байт
Объяснение:
Это фактическая утечка памяти, которая может произойти на любом языке, независимо от того, использует ли язык ручное управление памятью, автоматический подсчет ссылок (например, Swift) или даже уборку мусора.
[3,5]
это просто массив букв. Этот массив выделяет достаточно памяти как минимум для этих двух элементов.3
И5
просто произвольно.Подписание (индексация)
Array<T>
производитArraySlice<T>
. AnArraySlice<T>
- просмотр памяти массива, из которого он был создан.[3,5][0...0]
производитArraySlice<Int>
, чье значение[3]
. Обратите внимание, что3
в этом фрагменте тот же3
элемент, что и3
в оригинале,Array
показанном выше, а не копия.Полученный фрагмент можно затем сохранить в переменной и использовать. На исходный массив больше нет ссылок, поэтому вы могли бы подумать, что он может быть освобожден. Однако не может.
Поскольку срез предоставляет вид на память массива, из которого он получен, исходный массив должен сохраняться в течение всего срока жизни среза. Таким образом, из первоначального
2
объема памяти, который был выделен для размеров элементов, используется только первый размер памяти для элементов, а другой должен существовать, чтобы не выделять первый. Второй размер элемента памяти де-факто просочился.Решение этой проблемы состоит в том, чтобы долго не поддерживать маленькие кусочки больших массивов. Если вам нужно сохранить содержимое среза, поместите его в массив, который запустит копирование памяти, удалив зависимость от памяти исходного массива:
источник
Решение 1: C (Mac OS X x86_64), 109 байт
Источник для golf_sol1.c
Вышеупомянутая программа должна быть скомпилирована с доступом к исполнению в сегменте __DATA.
Затем для запуска программы выполните следующее:
Результаты:
К сожалению, Valgrind не отслеживает память, выделяемую из системных вызовов, поэтому я не могу показать хорошую обнаруженную утечку.
Однако мы можем посмотреть на vmmap, чтобы увидеть большой кусок выделенной памяти (метаданные MALLOC).
объяснение
Поэтому я думаю, что мне нужно описать, что на самом деле здесь происходит, прежде чем переходить к улучшенному решению.
Эта основная функция злоупотребляет отсутствующим объявлением типа C (поэтому по умолчанию используется int, и нам не нужно тратить на это символы), а также то, как работают символы. Компоновщик заботится только о том, может ли он найти символ, вызываемый
main
для вызова. Итак, здесь мы делаем main массив int, который мы инициализируем нашим шелл-кодом, который будет выполнен. Из-за этого main будет добавляться не к сегменту __TEXT, а к сегменту __DATA, поэтому нам нужно скомпилировать программу с исполняемым сегментом __DATA.Обнаружен шелл-код в main:
То, что это делает, вызывает функцию syscall для выделения страницы памяти (syscall mach_vm_allocate использует внутренне). RAX должен быть равен 0x100000a (сообщает системному вызову, какую функцию мы хотим), в то время как RDI содержит цель для выделения (в нашем случае мы хотим, чтобы это было mach_task_self ()), RSI должен содержать адрес для записи указателя во вновь созданную память (поэтому мы просто указываем на раздел в стеке), RDX содержит размер выделения (мы просто передаем RAX или 0x100000a, чтобы сэкономить на байтах), R10 содержит флаги (мы указываем, что он может выделяться где угодно).
Теперь не совсем очевидно, откуда RAX и RDI получают свои значения. Мы знаем, что RAX должен быть 0x100000a, а RDI должен быть значением, возвращаемым mach_task_self (). К счастью, mach_task_self () на самом деле является макросом для переменной (mach_task_self_), которая каждый раз находится по одному и тому же адресу памяти (однако при перезагрузке должна меняться). В моем конкретном случае mach_task_self_ находится по адресу 0x00007fff7d578244. Таким образом, чтобы сократить инструкции, мы вместо этого будем передавать эти данные из argv. Вот почему мы запускаем программу с этим выражением
$(ruby -e 'puts "\xf5\xff\xff\xfe\xff\xff\x44\x82\x57\x7d\xff\x7f"')
за первый аргумент. Строка представляет собой объединенные два значения, где значение RAX (0x100000a) составляет всего 32 бита и к нему применено одно дополнение (поэтому нулевых байтов нет; мы просто НЕ получаем значение, чтобы получить оригинал), следующее значение RDI (0x00007fff7d578244), который был смещен влево с 2 дополнительными ненужными байтами, добавленными в конец (снова, чтобы исключить нулевые байты, мы просто сдвигаем его обратно вправо, чтобы вернуть его к оригиналу).После системного вызова мы пишем в нашу недавно выделенную память. Причина этого в том, что память, выделенная с помощью mach_vm_allocate (или этого системного вызова), на самом деле является страницами виртуальной машины и не выгружается в память автоматически. Скорее они зарезервированы до тех пор, пока им не будут записаны данные, а затем эти страницы будут отображены в памяти. Не был уверен, что он будет соответствовать требованиям, если он будет только зарезервирован.
Для следующего решения мы воспользуемся преимуществом того факта, что наш шелл-код не имеет нулевых байтов и поэтому может переместить его за пределы кода нашей программы, чтобы уменьшить размер.
Решение 2: C (Mac OS X x86_64), 44 байта
Источник для golf_sol2.c
Вышеупомянутая программа должна быть скомпилирована с доступом к исполнению в сегменте __DATA.
Затем для запуска программы выполните следующее:
Результат должен быть таким же, как и раньше, поскольку мы делаем выделение того же размера.
объяснение
Следует той же концепции, что и решение 1, за исключением того, что мы переместили часть нашего утекшего кода за пределы программы.
Найденный в main шелл-код теперь выглядит следующим образом:
Это в основном копирует шелл-код, который мы передаем в argv, чтобы следовать за этим кодом (поэтому после того, как он скопировал его, он запустит вставленный шелл-код). Что работает в нашу пользу, так это то, что сегмент __DATA будет иметь размер как минимум страницы, поэтому даже если наш код не такой большой, мы все равно можем «безопасно» писать больше. Недостатком является идеальное решение здесь, даже не нужно копировать, вместо этого он просто вызовет и выполнит шелл-код напрямую в argv. Но, к сожалению, эта память не имеет прав на исполнение. Мы могли бы изменить права на эту память, однако для этого потребовалось бы больше кода, чем просто его копирование. Альтернативной стратегией будет изменение прав из внешней программы (но об этом позже).
Код шелла, который мы передаем в argv, выглядит следующим образом:
Это почти то же самое, что и наш предыдущий код, с той лишь разницей, что мы включаем значения для EAX и RDI напрямую.
Возможное решение 1: C (Mac OS X x86_64), 11 байт
Идея внешней модификации программы дает нам возможное решение о переносе лейкера во внешнюю программу. Где наша фактическая программа (представление) является просто фиктивной программой, и программа-лидер будет выделять часть памяти в нашей целевой программе. Теперь я не был уверен, подпадает ли это под правила для этого вызова, но все же поделился им.
Таким образом, если бы мы использовали mach_vm_allocate во внешней программе с целью, установленной для нашей программы испытаний, это могло бы означать, что наша программа испытаний должна была бы выглядеть примерно так:
Где этот шеллкод - просто короткий переход к самому себе (бесконечный переход / цикл), так что программа остается открытой, и мы можем ссылаться на нее из внешней программы.
Возможное решение 2: C (Mac OS X x86_64), 8 байт
Как ни странно, когда я смотрел на вывод valgrind, я видел, что, по крайней мере, в соответствии с valgrind, утечка памяти теряет память. Таким образом, каждая программа теряет память. В этом случае мы могли бы просто сделать программу, которая ничего не делает (просто завершает работу), и это фактически приводит к утечке памяти.
Источник:
источник
Простой английский ,
71705835 байтУдалил 1 байт, удалив пустую строку. Удалил 12 байтов, исключив определение типа «богона» и использовав родительский тип «вещь» вместо подтипа «богона». Удалил 23 байта, переключившись с полной программы на обычную процедуру, которая приводит к утечке памяти.
Гольф версия:
Версия без поддержки, которая является законченной программой, использует определение подтипа и не пропускает память:
Если вызывается версия «x» для игры в гольф, она будет пропускать память пропорционально количеству вызовов «x». В версии для гольфа "Распределить вещь". бы исправить утечку памяти.
Простой английский проверяет утечки памяти по умолчанию. Когда запускается версия с утечкой памяти, перед закрытием программы появляется диалоговое окно. Диалоговое окно имеет заголовок «отладка», сообщение «1 капель» и кнопку «ОК». Чем больше раз вызывается функция утечки, тем больше количество «капель» в сообщении. При запуске версии, не пропускающей память, диалоговое окно не отображается.
В простом английском языке «вещь» - это указатель на элемент в двусвязном списке. «Вещи», «запускать» и «выключать» определяются в модуле, называемом «лапшой», который необходимо скопировать (обычно в виде отдельного файла) в каждый проект. «A», «the», «to», «выделить память» и «уничтожить» определены в компиляторе.
источник