Vazamento de memória no menor número de bytes possível


79

Sua tarefa é escrever um código que vaze pelo menos um byte de memória no menor número possível de bytes. A memória deve ter vazamento e não apenas alocada .

Memória vazada é a memória que o programa aloca, mas perde a capacidade de acessar antes de poder desalocar a memória adequadamente. Para a maioria dos idiomas de alto nível, essa memória deve ser alocada no heap.

Um exemplo em C ++ seria o seguinte programa:

int main(){new int;}

Isso cria um new intheap sem um ponteiro para ele. Essa memória vaza instantaneamente porque não temos como acessá-la.

Aqui está a aparência de um resumo de vazamento da 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

Muitos idiomas têm um depurador de memória (como o Valgrind ), se você puder incluir a saída desse depurador para confirmar se há memória vazada.

O objetivo é minimizar o número de bytes em sua fonte.


2
Talvez você possa ter diferentes faixas de quantidade vazadas e, dependendo de quanto você vaza, perde x% da sua contagem de bytes.
Christopher

11
@ChristopherPeart Por um lado, não sou fã de bônus em desafios e por dois, como você já demonstrou, é muito fácil vazar memória ilimitada.
Assistente de Trigo

1
Relacionado . Porém, não é uma duplicata, porque a maioria das respostas a essa pergunta forma uma estrutura infinitamente acessível na memória, em vez de realmente vazar memória.

2
qual é a ideia? Que o mem não pode ser libertado? Eu acho que isso exigiria execução nativa para idiomas coletados pelo lixo ou exploração de bugs.
akostadinov

7
Eu vejo como línguas projetados para jogar golfe falhar miseravelmente em um presente ...
Kh40tiK

Respostas:


89

Perl (5.22.2), 0 bytes

Experimente online!

Eu sabia que haveria alguma linguagem por aí que vazaria memória em um programa vazio. Eu esperava que fosse um esolang, mas acontece que perlvaza memória em qualquer programa. (Suponho que isso seja intencional, porque liberar memória, se você sabe que vai sair de qualquer maneira, perde tempo; como tal, a recomendação comum hoje em dia é vazar a memória restante assim que você estiver nas rotinas de saída do programa .)

Verificação

$ echo -n | valgrind perl
snip
==18517== 
==18517== LEAK SUMMARY:
==18517==    definitely lost: 8,134 bytes in 15 blocks
==18517==    indirectly lost: 154,523 bytes in 713 blocks
==18517==      possibly lost: 0 bytes in 0 blocks
==18517==    still reachable: 0 bytes in 0 blocks
==18517==         suppressed: 0 bytes in 0 blocks
==18517== 
==18517== For counts of detected and suppressed errors, rerun with: -v
==18517== ERROR SUMMARY: 15 errors from 15 contexts (suppressed: 0 from 0)

16
Gostei da resposta da Unlambda, mas essa é (IMHO) muito extensa, pois é obviamente o próprio intérprete que vaza a memória, ou seja, eu fico `definitivamente perdido: 7.742 bytes em 14 blocos 'quando corro perl --versionna máquina , apesar de nunca conseguir executar nenhum programa.
Zeppelin

11
@ zeppelin: Concordo, mas de acordo com nossas regras, é a implementação que define a linguagem, portanto, se a implementação vazar memória, todos os programas na linguagem vazarão memória. Não tenho necessariamente certeza de que concordo com essa regra, mas, neste momento, está muito arraigado para poder realmente mudar.

8
Isso também funciona no Nó JS.
Dennis

6
Este se sente como uma nova brecha padrão na tomada de ...
Michael Hampton

46
Finalmente, um script Perl que eu possa entender.
user11153

66

C, 48 31 22 bytes

Aviso: não execute isso muitas vezes.

Obrigado a Dennis por muita ajuda / idéias!

f(k){shmget(k,1,512);}

Isso vai um passo adiante. shmgetaloca memória compartilhada que não é desalocada quando o programa termina. Ele usa uma chave para identificar a memória, então usamos um int não inicializado. Esse é um comportamento tecnicamente indefinido, mas praticamente significa que usamos o valor que está logo acima do topo da pilha quando isso é chamado. Isso será gravado na próxima vez que algo for adicionado à pilha, então perderemos a chave.


O único caso em que isso não funciona é se você pode descobrir o que estava na pilha antes. Por mais 19 bytes extras, você pode evitar este problema:

f(){srand(time(0));shmget(rand(),1,512);}

Ou, para 26 bytes:

main(k){shmget(&k,1,512);}

Mas com este, a memória vaza após a saída do programa. Durante a execução, o programa tem acesso à memória que é contrária às regras, mas após o término do programa, perdemos o acesso à chave e a memória ainda está alocada. Isso requer a randomização do layout do espaço de endereço (ASLR), caso contrário &kserá sempre o mesmo. Atualmente, o ASLR normalmente está ativado por padrão.


Verificação:

Você pode usar ipcs -mpara ver qual memória compartilhada existe no seu sistema. Eu removi entradas pré-existentes para maior clareza:

$ cat leakMem.c 
f(k){shmget(k,1,512);}
int main(){f();}     
$ gcc leakMem.c -o leakMem
leakMem.c:1:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
 f(k){shmget(k,1,512);}
 ^
leakMem.c: In function ‘f’:
leakMem.c:1:1: warning: type of ‘k’ defaults to ‘int’ [-Wimplicit-int]
leakMem.c:1:6: warning: implicit declaration of function ‘shmget’ [-Wimplicit-function-declaration]
 f(k){shmget(k,1,512);}
ppcg:ipcs -m

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      


$ ./leakMem 

$ ipcs -m

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      

0x0000007b 3375157    Riley      0          1          0  

1
@AndrewSavinykh Teoricamente, o shmid poderia ter sido armazenado em um arquivo e um programa poderia ser anexado a ele no futuro. Isto é como unix memória compartilhada funciona ...
tbodt

1
@AndrewSavinykh A memória compartilhada basicamente se torna um recurso que o sistema operacional pode oferecer a outros processos. É semelhante a um arquivo que vive na RAM e qualquer processo que sabe o nome (chave) tem acesso a ele até que seja excluído. Imagine um processo que calcula um número e o armazena na memória e sai antes que o processo que lê os dados se conecte à memória compartilhada. Nesse caso, se o sistema operacional libera a memória, o segundo processo não pode ser obtido.
Riley

35
Obrigado por postar isso. Acabei de proteger o TIO contra vazamentos de memória compartilhada.
Dennis

4
@ Dennis É por isso que não postei um link TIO. Não sabia se estava protegido ou não.
Riley

12
Gosto de como você usa a palavra problema para descrever o cenário em que o programa vaza menos memória do que o pretendido.
kasperd

40

Unlambda ( c-refcnt/unlambda), 1 byte

i

Experimente online!

É realmente um desafio encontrar um intérprete pré-existente que vaze memória em programas muito simples. Nesse caso, usei o Unlambda. Há mais de um intérprete oficial da Unlambda, mas c-refcnté um dos mais fáceis de construir, e possui a propriedade útil de vazar memória quando um programa é executado com êxito. Então, tudo o que eu precisava dar aqui era o programa Unlambda legal mais simples possível, um não operacional. (Observe que o programa vazio não funciona aqui; a memória ainda pode ser acessada no momento em que o intérprete falha).

Verificação

$ wget ftp://ftp.madore.org/pub/madore/unlambda/unlambda-2.0.0.tar.gz
…recorte…
18-02-2017 18:11:08 (975 KB / s) - 'unlambda-2.0.0.tar.gz' salvo [492894]
$ tar xf unlambda-2.0.0.tar.gz 
$ cd unlambda-2.0.0 / c-refcnt /
$ gcc unlambda.c
$ echo -ni | valgrind ./a.out / dev / stdin
…recorte…
== 3417 == RESUMO DE VAZAMENTO:
== 3417 == definitivamente perdido: 40 bytes em 1 bloco
== 3417 == indiretamente perdido: 0 bytes em 0 blocos
== 3417 == possivelmente perdido: 0 bytes em 0 blocos
== 3417 == ainda acessível: 0 bytes em 0 blocos
== 3417 == suprimido: 0 bytes em 0 blocos
== 3417 == 
== 3417 == Para contagens de erros detectados e suprimidos, execute novamente com: -v
== 3417 == RESUMO DE ERROS: 1 erro em 1 contexto (suprimido: 0 em 0)

39

TI-Basic, 12 bytes

While 1
Goto A
End
Lbl A
Pause 

"... um vazamento de memória é onde você usa Goto / Lbl dentro de um loop ou If condicional (qualquer coisa que possua um comando End) para pular fora dessa estrutura de controle antes que o comando End seja alcançado ..." (mais)


7
Uau, acho que me lembro disso. Eu ficava pulando para fora dos meus loops em meus velhos programas básicos e notou como a minha TI-84 + ficou mais lento e mais lento ...
Ray

2
Sim, a maioria de nós sabe o sentimento;) @RayKoopa
Timtech

13
+1 para o Ti Basic. Passei a maior parte do meu ano da 9ª série programando essas coisas.
markasoftware

Você precisa Pause no final? Você pode salvar 2 bytes.
kamoroso94

@ kamoroso94 Acho que sim, porque "Se um programa terminar, o vazamento será limpo e não causará mais problemas", então é para impedir que o programa termine.
Timtech 19/02

32

Python <3.6.5, 23 bytes

property([]).__init__()

property.__init__vazamentos referências ao da antiga propriedade fget, fset, fdel, e __doc__se você chamá-lo em um já inicializada propertyinstância. Esse é um erro, eventualmente relatado como parte do problema 31787 do CPython e corrigido no Python 3.6.5 e Python 3.7.0 . (Além disso, sim, property([])é algo que você pode fazer.)


Um relatório de bug foi enviado?
mbomb007


27

C #, 34 bytes

class L{~L(){for(;;)new L();}}

Esta solução não requer o Heap. Ele só precisa de um GC realmente trabalhador ( Garbage Collector ).

Essencialmente, transforma o GC em seu próprio inimigo.

Explicação

Sempre que o destruidor é chamado, ele cria novas instâncias dessa classe maligna, desde que o tempo limite se esgote e diz ao GC para abandonar esse objeto sem esperar que o destruidor termine. Até então, milhares de novas instâncias foram criadas.

A "maldade" disso é que, quanto mais o GC está trabalhando, mais isso vai explodir na sua cara.

Isenção de responsabilidade : seu GC pode ser mais inteligente que o meu. Outras circunstâncias no programa podem fazer com que o GC ignore o primeiro objeto ou seu destruidor. Nesses casos, isso não explodirá. Mas em muitas variações será . A adição de alguns bytes aqui e ali pode garantir um vazamento para todas as circunstâncias possíveis. Bem, exceto pelo interruptor, talvez.

Teste

Aqui está uma suíte de testes :

using System;
using System.Threading;
using System.Diagnostics;
class LeakTest {
    public static void Main() {
        SpawnLeakage();
        Console.WriteLine("{0}-: Objects may be freed now", DateTime.Now);
        // any managed object created in SpawbLeakage 
        //  is no longer accessible
        // The GC should take care of them

        // Now let's see
        MonitorGC();
    }
    public static void SpawnLeakage() {
        Console.WriteLine("{0}-: Creating 'leakage' object", DateTime.Now);
        L l = new L();
    }
    public static void MonitorGC() {
        while(true) {
            int top = Console.CursorTop;
            int left = Console.CursorLeft;
            Console.WriteLine(
                "{0}-: Total managed memory: {1} bytes",
                DateTime.Now,
                GC.GetTotalMemory(false)
            );
            Console.SetCursorPosition(left, top);
        }
    }
}

Saída após 10 minutos:

2/19/2017 2:12:18 PM-: Creating 'leakage' object
2/19/2017 2:12:18 PM-: Objects may be freed now
2/19/2017 2:22:36 PM-: Total managed memory: 2684476624 bytes

São 2 684 476 624 bytes. O total WorkingSetdo processo foi de cerca de 4,8 GB

Esta resposta foi inspirada no maravilhoso artigo de Eric Lippert: Quando tudo que você sabe está errado .


Isso é fascinante. O coletor de lixo "esquece" que algumas coisas existem e as perde por causa disso? Eu não sei muito sobre c #. Também agora estou me perguntando, qual é a diferença entre uma bomba e um vazamento? Eu imagino que um fiasco semelhante possa ser criado chamando um construtor de dentro de um construtor, ou tendo uma função recorrente infinita que nunca para, embora tecnicamente o sistema nunca perca o controle dessas referências, ele fica sem espaço ...
don brilhante

1
Um construtor dentro de um construtor causaria um estouro de pilha. Mas o destruidor de uma instância é chamado em uma hierarquia plana. Na verdade, o GC nunca perde o controle dos objetos. Sempre que tenta destruí-los, involuntariamente cria novos objetos. O código do usuário, por outro lado, não tem acesso aos referidos objetos. Além disso, as inconsistências mencionadas podem surgir, pois o GC pode decidir destruir um objeto sem chamar seu destruidor.
MrPaulch

O desafio não seria completo usando apenas class L{~L(){new L();}}? AFAIK é o for(;;)único que faz vazar memória mais rapidamente, certo?
BgrWorker

1
Infelizmente não. Como para cada objeto destruído, apenas uma nova instância será criada, que novamente estará inacessível e marcada para destruição. Repetir. Apenas um objeto estará pendente de destruição. Não há população crescente.
21417 MrPaulch

2
Na verdade não. Eventualmente, um finalizado será ignorado. O objeto correspondente será comido independentemente.
MrPaulch

26

C (gcc) , 15 bytes

f(){malloc(1);}

Verificação

$ cat leak.c
f(){malloc(1);}
main(){f();}
$ gcc -g -o leak leak.c
leak.c: In function ‘f’:
leak.c:1:5: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
 f(){malloc(1);}
     ^
$ valgrind --leak-check=full ./leak
==32091== Memcheck, a memory error detector
==32091== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==32091== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==32091== Command: ./leak
==32091==
==32091==
==32091== HEAP SUMMARY:
==32091==     in use at exit: 1 bytes in 1 blocks
==32091==   total heap usage: 1 allocs, 0 frees, 1 bytes allocated
==32091==
==32091== 1 bytes in 1 blocks are definitely lost in loss record 1 of 1
==32091==    at 0x4C29110: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==32091==    by 0x40056A: f (leak.c:1)
==32091==    by 0x40057A: main (leak.c:2)
==32091==
==32091== LEAK SUMMARY:
==32091==    definitely lost: 1 bytes in 1 blocks
==32091==    indirectly lost: 0 bytes in 0 blocks
==32091==      possibly lost: 0 bytes in 0 blocks
==32091==    still reachable: 0 bytes in 0 blocks
==32091==         suppressed: 0 bytes in 0 blocks
==32091==
==32091== For counts of detected and suppressed errors, rerun with: -v
==32091== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

26

Javascript, 14 bytes

Golfe

setInterval(0)

Registra um manipulador de intervalo vazio com um atraso padrão, descartando o ID do timer resultante (impossibilitando o cancelamento).

insira a descrição da imagem aqui

Eu usei um intervalo não padrão, para criar vários milhões de temporizadores, para ilustrar o vazamento, pois o uso de um intervalo padrão consome a CPU como um louco.


5
Haha Eu amo que você digitou 'Golfed', faz-me curioso sobre a versão ungolfed
Martijn

9
pode ser assimif(window && window.setInterval && typeof window.setInterval === 'function') { window.setInterval(0); }
Tschallacka

3
Na verdade, isso não é impossível de cancelar: os IDs de intervalo (e tempo limite) são numerados sequencialmente; portanto, é bastante fácil cancelar a coisa apenas ligando clearIntervalcom um ID de incremento até que o intervalo se esgote. Por exemplo:for(let i=0;i<1e5;i++){try{clearInterval(i);}catch(ex){}}
user2428118

5
@ user2428118 Como zeppelin diz, este não é mais "legitmate" do que dizer os vazamentos C / C ++ não são "real" porque você poderia bruta chamadas de força parafree()
TripeHound

1
Uau, não muitos desafios, onde JavaScript é um concorrente real ...
Jared Smith

19

Java, 10 bytes

Finalmente, uma resposta competitiva em Java!

Golfe

". "::trim

Esta é uma referência de método (contra uma constante de cadeia), que pode ser usada assim:

Supplier<String> r = ". "::trim

Uma string literal ". "será automaticamente adicionado ao global internado piscina cordas, como sustenta a java.lang.Stringclasse, e como nós immediatelly prepará-la, a referência a ele não podem ser reutilizados mais no código (a menos que você declarar exatamente a mesma seqüência novamente).

...

Um pool de strings, inicialmente vazio, é mantido em particular pela classe String.

Todas as cadeias literais e expressões constantes com valor de cadeia são internadas. Os literais de sequência são definidos na seção 3.10.5 da Especificação da linguagem Java ™.

...

https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#intern--

Você pode transformar isso em um vazamento de memória "grau de produção", adicionando a sequência a si mesma e, em seguida, invocando o método intern () explicitamente, em um loop.


2
Eu considerei isso para C # ... mas acho que não conta, porque, como você diz, pode acessar essa memória incluindo outra string literal. Eu também estaria interessado em saber o ("." + " ").intern()que faria (se eles fossem dados do usuário ou não, por isso desconsideramos as otimizações do compilador).
Visual Febon '19

1
Na verdade, o único consenso é pequeno, na melhor das hipóteses, estou firmemente do lado "o código deve compilar". Ainda não tenho certeza de que comprei esta solução, dada a redação da pergunta (essas seqüências não podem ser liberadas e podem ser encontradas no código operacional normal, mesmo que seja improvável), mas convido outras pessoas a fazerem seu próprio julgamento
VisualMelon

3
Essa corda não é sequer inacessível , muito menos vazou. Podemos recuperá-lo a qualquer momento, internando uma sequência igual. Se isso contasse, qualquer variável global não utilizada (estática privada em Java) seria um vazamento. Não é assim que os vazamentos de memória são definidos.
user2357112

3
@ user2357112 "... Essa cadeia não é inacessível ..." Isso parece óbvio porque você vê o código. Agora, considere que você obteve essa referência de método X () como um argumento para o seu código, você sabe que ele aloca (e estica) uma string literal dentro, mas você não sabe qual exatamente, pode ser "." Ou "123" ou qualquer outra cadeia de comprimento (geralmente) desconhecida. Você poderia demonstrar como ainda pode acessá-lo ou desalocar a entrada no pool "interno" que ocupa?
Zeppelin

2
@ user2357112 Em uma máquina com memória finita, você pode acessar um valor armazenado em qualquer parte da memória simply by guessing it correctly, mas isso não significa que não exista um vazamento de memória. there's probably some way to use reflection to determine the string's contents toovocê poderia demonstrar isso? (dica, String.intern () é implementada no código nativo ).
Zeppelin

17

Ferrugem, 52 bytes

extern{fn malloc(_:u8);}fn main(){unsafe{malloc(9)}}

Aloca alguns bytes com o sistema malloc. Isso pressupõe que o ABI errado seja aceitável.


Ferrugem (em teoria), 38 bytes

fn main(){Box::into_raw(Box::new(1));}

Alocamos memória na pilha, extraímos um ponteiro bruto e depois a ignoramos, vazando efetivamente. ( Box::into_rawé mais curto então std::mem::forget).

No entanto, o Rust, por padrão, usa jemalloc, que o valgrind não pode detectar nenhum vazamento . Poderíamos mudar para o alocador de sistema, mas isso adiciona 50 bytes e requer todas as noites. Muito obrigado pela segurança da memória.


Saída do primeiro programa:

==10228== Memcheck, a memory error detector
==10228== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==10228== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==10228== Command: ./1
==10228== 
==10228== 
==10228== HEAP SUMMARY:
==10228==     in use at exit: 9 bytes in 1 blocks
==10228==   total heap usage: 7 allocs, 6 frees, 2,009 bytes allocated
==10228== 
==10228== LEAK SUMMARY:
==10228==    definitely lost: 9 bytes in 1 blocks
==10228==    indirectly lost: 0 bytes in 0 blocks
==10228==      possibly lost: 0 bytes in 0 blocks
==10228==    still reachable: 0 bytes in 0 blocks
==10228==         suppressed: 0 bytes in 0 blocks
==10228== Rerun with --leak-check=full to see details of leaked memory
==10228== 
==10228== For counts of detected and suppressed errors, rerun with: -v
==10228== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

impressionante. posts como esse me levaram a explorar o Rust no ano passado, definitivamente uma das línguas mais divertidas que tentei aprender.
don bright

16

8086 ASM, 3 bytes

Este exemplo pressupõe que um tempo de execução C esteja vinculado.

jmp _malloc

isso monta para e9 XX XXonde XX XXestá o endereço relativo de_malloc

Isso chama mallocpara alocar uma quantidade imprevisível de memória e, em seguida, retorna imediatamente, encerrando os processos. Em alguns sistemas operacionais como o DOS, a memória pode não ser recuperada até que o sistema seja reiniciado!


A implementação normal do malloc resultará na liberação da memória na saída do processo.
Joshua

@ Josué Sim, mas isso é comportamento definido de implementação.
FUZxxl

12

Quarto, 6 bytes

Golfe

s" " *

Aloca uma string vazia com s" ", deixando o endereço e o comprimento (0) na pilha e depois os multiplica (resultando na perda de um endereço de memória).

Valgrind

%valgrind --leak-check=full gforth -e 's" " * bye'
...
==12788== HEAP SUMMARY:
==12788==     in use at exit: 223,855 bytes in 3,129 blocks
==12788==   total heap usage: 7,289 allocs, 4,160 frees, 552,500 bytes allocated
==12788== 
==12788== 1 bytes in 1 blocks are definitely lost in loss record 1 of 22
==12788==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12788==    by 0x406E39: gforth_engine (in /usr/bin/gforth-0.7.0)
==12788==    by 0x41156A: gforth_go (in /usr/bin/gforth-0.7.0)
==12788==    by 0x403F9A: main (in /usr/bin/gforth-0.7.0)
==12788== 
...
==12818== LEAK SUMMARY:
==12818==    definitely lost: 1 bytes in 1 blocks
==12818==    indirectly lost: 0 bytes in 0 blocks

10

vá 45 bytes

package main
func main(){go func(){for{}}()}

isso cria uma goroutine anônima com um loop infinito dentro dela. o programa pode continuar funcionando normalmente, pois iniciar a goroutine é como gerar um thread pequeno em execução simultânea, mas o programa não tem como recuperar a memória que foi alocada para a goroutine. o coletor de lixo nunca o coletará, pois ainda está em execução. algumas pessoas chamam isso de 'vazar uma goroutine'


verificação de golfe: este é 2 bytes menor do que chamar C.malloc(8), já que você precisaimport"C"
Riking

9

Java 1.3, 23 bytes

void l(){new Thread();}

Criando um encadeamento, mas não iniciando-o. O encadeamento é registrado no pool de encadeamentos interno, mas nunca será iniciado, portanto, nunca será encerrado e, portanto, nunca será candidato ao GC. É um objeto irrecuperável, preso nos limbos do Java.

É um bug no Java até a versão 1.3 incluída , pois foi corrigida posteriormente.

Testando

O programa a seguir certifica-se de poluir a memória com novos objetos de encadeamento e mostra um espaço de memória livre decrescente. Para fins de teste de vazamentos, intensamente faço o GC funcionar.

public class Pcg110485 {

    static
    void l(){new Thread();}

    public static void main(String[] args) {

        while(true){
            l();
            System.gc();
            System.out.println(Runtime.getRuntime().freeMemory());
        }
    }
}

Como isso funciona apenas em versões Java específicas, você deve dizer "Java 3" em seu cabeçalho.

5
Não existe o Java 3. É o Java 1.3. Havia Java 1.0, 1.1, 2, 1.3, 1.4, 5, 6, 7, 8, 9. Numeração estranha, mas é assim.
Olivier Grégoire

Essa foi minha ideia também. Droga.
Magic Octopus Urn

8

Befunge ( fungos ), 1 byte

$

Isso pode depender da plataforma e da versão (eu testei apenas com a versão 1.0.4 no Windows), mas os fungos historicamente têm sido um intérprete muito vazado. O $comando (drop) não deve fazer nada em uma pilha vazia, mas repetir esse código de alguma forma consegue vazar muita memória muito rapidamente. Em questão de segundos, ele esgotou alguns shows e trava com um erro de "falta de memória".

Observe que ele não precisa necessariamente ser um $comando - praticamente qualquer coisa faria. Porém, ele não funcionará com um arquivo de origem em branco. Tem que haver pelo menos uma operação.


8

Swift 3, 38 bytes

Nova versão:

class X{var x: X!};do{let x=X();x.x=x}

x tem uma forte referência a si próprio, para que não seja desalocado, levando a um vazamento de memória.

Versão antiga:

class X{var y:Y!}
class Y{var x:X!}
do{let x=X();let y=Y();x.y=y;y.x=x}

xcontém uma forte referência ye vice-versa. Assim, nenhum deles será desalocado, levando a um vazamento de memória.


Hmm, você ainda pode fazer referência a essa memória xe y, portanto, isso realmente não parece um vazamento para mim (a menos que você os destrua de alguma forma).
Zeppelin

@zeppelin A última linha poderia ser envolvido em uma função de corrigir isso
NobodyNada

@NobodyNada, se eu colocasse a última linha em um dobloco que resolveria o problema que o zeppelin levantou, certo?
Daniel

@Dopapp Yeah; um dofuncionaria também. Boa ideia!
NobodyNada

Ele pode ser encurtado, você não precisa de duas classes - X pode conter referência a si mesmo:class X{var x: X!};do{let x=X();x.x=x}
Sebastian Osiński

7

Delphi (Object Pascal) - 33 bytes

Criando um objeto sem um programa de console completo variável:

program;begin TObject.Create;end.

A ativação do FastMM4 no projeto mostrará o vazamento de memória:

insira a descrição da imagem aqui


6

C # - 84 bytes

class P{static void Main(){System.Runtime.InteropServices.Marshal.AllocHGlobal(1);}}

Isso aloca exatamente 1 byte de memória não gerenciada e perde a IntPtr, que acredito ser a única maneira de obter ou liberá-la. Você pode testá-lo colocando-o em um loop e aguardando a falha do aplicativo (pode querer adicionar alguns zeros para acelerar as coisas).

Eu considerei System.IO.File.Create("a");e tal, mas eu não estou convencido de que estes são, necessariamente, vazamentos de memória, como o próprio aplicativo irá coletar a memória, é o OS embaixo que pode vazar (porque Closeou Disposenão foram chamados). O acesso a arquivos também requer permissões do sistema de arquivos e ninguém deseja confiar nelas. E, de qualquer forma, isso não vazará, porque não há nada que impeça a chamada do finalizador (o que liberta os recursos subjacentes é possível), que a estrutura inclui para atenuar esses tipos de erros de julgamento (até certo ponto) e confundir programadores com bloqueio de arquivos aparentemente não determinístico (se você é um cínico). Agradeço a Jon Hanna por me esclarecer isso.

Estou um pouco decepcionado por não encontrar um caminho mais curto. O .NET GC funciona, não consigo pensar em nada IDisposablesno mscorlib que vazará definitivamente (e, de fato, todos parecem ter finalizadores, que chato) , não conheço outra maneira de alocar memória não gerenciada (com falta de PInvoke ), e a reflexão garante que qualquer coisa com uma referência a ele (independentemente da semântica do idioma (por exemplo, membros privados ou classes sem acessadores)) possa ser encontrada.


1
System.IO.File.Create("a")não vai vazar nada, mas GC.SuppressFinalize(System.IO.File.Create("a"))vai, como é explicitamente solicitado a não executar o finalizador do FileStreamproduzido.
Jon Hanna

@ JonHanna bastante certo. Minha paranóia descartável parece ter me superado.
VisualMelon

Você pode ter a chance de fazer o GDI + vazar usando System.Drawing.Bitmap. Não sei se conta, porque é uma biblioteca do Windows que está causando o vazamento, não o próprio programa.
BgrWorker

@BgrWorker, sem dúvida, eles também têm um finalizador, e eu tendem a evitar bibliotecas externas em code-golf porque não concordo com o consenso de custá-las: se você puder encontrar uma maneira de confiar, sinta-se à vontade para postar na sua própria resposta!
VisualMelon

<!-- language: lang-c# -->Obrigado por esta e boa resposta! (É C #, então eu amo isso)
Metoniem

5

Fator , 13 bytes

O fator possui gerenciamento automático de memória, mas também fornece acesso a algumas funcionalidades da libc:

1 malloc drop

Aloca manualmente 1 byte de memória, retorna seu endereço e o elimina.

malloc na verdade, registra uma cópia para rastrear vazamentos de memória e liberar duas vezes, mas identificar o que você vazou não é uma tarefa fácil.

Se você preferir se certificar de que realmente perde essa referência:

1 (malloc) drop

O teste de vazamentos [ 1 malloc drop ] leaks.diz:

| Disposable class | Instances |                    |
| malloc-ptr       | 1         | [ List instances ] |

O teste de vazamentos [ 1 (malloc) drop ] leaks.diz:

| Disposable class | Instances | |

Ah não! Pobre fator, ele tem Alzheimer agora! D:


4

AutoIt , 39 bytes

#include<Memory.au3>
_MemGlobalAlloc(1)

Aloca um byte do heap. Como o identificador retornado por _MemGlobalAllocé descartado, não há como liberar explicitamente essa alocação.


4

Lisp comum (apenas SBCL), 28. 26 bytes

sb-alien::(make-alien int)

Você executa assim sbcl --eval 'sb-alien::(make-alien int)':; nada é impresso nem retornado, mas a alocação de memória acontece. Se eu envolver o formulário dentro de a (print ...), o ponteiro será exibido no REPL.

  1. package::(form)é uma notação especial no SBCL para vincular temporariamente o pacote atual ao ler um formulário. Isso é usado aqui para evitar prefixar ambos make-aliene intcom sb-alien. Eu acho que seria trapaça assumir que o pacote atual está definido para este, porque esse não é o caso na inicialização.

  2. make-alien aloca memória para um determinado tipo e um tamanho opcional (usando malloc).

  3. Ao executar isso no REPL, adicione 0após a alocação para que o REPL não retorne o ponteiro, mas esse valor. Caso contrário, que sem ser uma verdadeira fuga porque o REPL se lembra dos últimos três valores devolvidos (Veja *, **,*** ) e nós ainda poderia ter uma chance de liberar a memória alocada.

2 bytes removidos graças a PrzemysławP, obrigado!


1
Você não pode usar 1(ou 2, 3etc.) em vez de ()retornar valor 1? Isso economizaria 1 byte. Também esta resposta é apenas REPL? Talvez se você carregar código com loadvocê não pode incluir ()ou qualquer coisa no final, porque ele não estará acessível de qualquer maneira?

1
@ PrzemysławP Você está certo em ambos os pontos, tentei evale isso funciona como você disse. Muito obrigado!
Coredump

3

C ++, 16 bytes

main(){new int;}

Não tenho o valgrind para verificar se há vazamentos, mas com certeza deveria. Caso contrário, eu tentaria:

main(){[]{new int;}();}

Resultado Valgrind

(Ele realmente vaza)

==708== LEAK SUMMARY:
==708==    definitely lost: 4 bytes in 1 blocks

@ WheatWizard que estou usando g++ 4.3.2(não o mais recente) e compila muito bem. Nenhum tipo de retorno é intpor padrão, eu acho. Com -Walleu tenho um aviso:plop.cpp:1: warning: ISO C++ forbids declaration of 'main' with no type
matovitch

2
@ WheatWizard Desculpe, acabei de ver que você deu o exemplo de c ++ para iniciar o concurso. Vindo do reddit, olhei apenas as respostas e (estranhamente) não vi nenhum C ++. Eu me sinto um pouco idiota. : /
matovitch 20/02

O consenso é que você pode contar []{new int;}como uma função C ++ (o desafio não especificou um programa inteiro).
Toby Speight

3

Java (OpenJDK 9) , 322 220 bytes

import sun.misc.*;class Main{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);}}

Experimente online!

Este é outro vazamento de memória que não usa o cache de strings. Aloca metade da sua RAM e você não pode fazer nada com ela.

Obrigado ao zeppelin por salvar todos os bytes


Você pode salvar um monte de bytes por obter o Unsafeexemplo da variável estática dentro dele, assim: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);}}
zeppelin

E você pode economizar um pouco mais, substituindo o public static void mainpor um inicializador estático static{try{}catch(Exception e){}}(que pode ser um pouco mais difícil de iniciar, mas é válido e compilável).
Zeppelin

Sim, o uso do construtor foi usado em uma versão Android do código que eu usei. Vou mudar algumas coisas quando estou @Home mas vou seguir o caminho que você foi com uma única instrução;)
Serverfrog

Remova os espaços em branco, use em avez de argse remova o público. tio.run/nexus/…
Pavel

true pode ser substituído por 1> 0
masterX244 23/02

3

c, 9 bytes

main(){}

Prova:

localhost/home/elronnd-10061: cat t.c
main(){}
localhost/home/elronnd-10062: valgrind gcc t.c
==10092== Memcheck, a memory error detector
==10092== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==10092== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==10092== Command: gcc t.c
==10092==
t.c:1:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
 main(){}
 ^~~~
==10092==
==10092== HEAP SUMMARY:
==10092==     in use at exit: 178,518 bytes in 73 blocks
==10092==   total heap usage: 362 allocs, 289 frees, 230,415 bytes allocated
==10092==
==10092== LEAK SUMMARY:
==10092==    definitely lost: 4,659 bytes in 8 blocks
==10092==    indirectly lost: 82 bytes in 5 blocks
==10092==      possibly lost: 0 bytes in 0 blocks
==10092==    still reachable: 173,777 bytes in 60 blocks
==10092==         suppressed: 0 bytes in 0 blocks
==10092== Rerun with --leak-check=full to see details of leaked memory
==10092==
==10092== For counts of detected and suppressed errors, rerun with: -v
==10092== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

1
Você não está realmente perdendo memória; gccé. Isso também deve funcionar com o programa vazio. Tente gcc src.c && valgrind ./a.out, o que deve produzir um resultado limpo.

3

C #, 109 bytes

public class P{static void Main({for(;;)System.Xml.Serialization.XmlSerializer.FromTypes(new[]{typeof(P)});}}

Descobrimos a idéia por trás desse vazamento no código de produção e pesquisá-lo leva a este artigo. O principal problema está nesta longa citação do artigo (leia-o para obter mais informações):

Pesquisando meu código por PurchaseOrder, encontro esta linha de código em page_loaduma de minhas páginasXmlSerializer serializer = new XmlSerializer(typeof(PurchaseOrder), new XmlRootAttribute(“”));

Isso pareceria um pedaço de código bastante inocente. Criamos um XMLSerializerpara PurchaseOrder. Mas o que acontece debaixo das cobertas?

Se dermos uma olhada no XmlSerializerconstrutor com o Reflector, descobrimos que ele chama, o this.tempAssembly = XmlSerializer.GenerateTempAssembly(this.mapping, type, defaultNamespace, location, evidence);que gera uma montagem temp (dinâmica). Portanto, toda vez que esse código é executado (ou seja, toda vez que a página é acessada), ele gera um novo assembly.

O motivo de gerar uma montagem é que ela precisa gerar funções para serializar e desserializar e que elas precisam residir em algum lugar.

Ok, tudo bem ... ele cria uma montagem, e daí? Quando terminamos, ele deveria desaparecer, certo?

Bem ... uma montagem não é um objeto no Heap do GC, o GC realmente não tem conhecimento das montagens, portanto não coletará lixo. A única maneira de se livrar dos assemblies em 1.0 e 1.1 é descarregar o domínio do aplicativo em que ele reside.

E aí está o problema, Dr. Watson.

A execução do compilador no Visual Studio 2015 e a janela Ferramentas de diagnóstico mostra os seguintes resultados após cerca de 38 segundos. Observe que a memória do processo está subindo constantemente e o Garbage Collector (GC) continua em execução, mas não pode coletar nada.

Janela Ferramentas de diagnóstico


2

C 30 bytes

f(){int *i=malloc(sizeof(4));}

Resultados de Valgrind:

         ==26311== HEAP SUMMARY:
         ==26311==     in use at exit: 4 bytes in 1 blocks
         ==26311==   total heap usage: 1 allocs, 0 frees, 4 bytes allocated
         ==26311== 
         ==26311== LEAK SUMMARY:
         ==26311==    definitely lost: 4 bytes in 1 blocks
         ==26311==    indirectly lost: 0 bytes in 0 blocks
         ==26311==      possibly lost: 0 bytes in 0 blocks
         ==26311==    still reachable: 0 bytes in 0 blocks
         ==26311==         suppressed: 0 bytes in 0 blocks
         ==26311== Rerun with --leak-check=full to see details of leaked memory

2
É possível apenas fazer main(){malloc(1);}?
Kirbyfan64sos

@Sim, é isso! Mas já foi publicado!
Abel Tom

2

Dardo, 76 bytes

import'dart:async';main()=>new Stream.periodic(Duration.ZERO).listen((_){});

Um pouco como a resposta JavaScript. Quando você chama .listenum objeto de fluxo Dart, recebe de volta um StreamSubscription, que permite desconectar-se do fluxo. No entanto, se você jogar fora isso, nunca poderá cancelar a inscrição no fluxo, causando um vazamento. A única maneira de corrigir o vazamento é se o próprio Stream for coletado, mas ele ainda é referenciado internamente por um combo StreamController + Timer.

Infelizmente, o Dart é inteligente demais para as outras coisas que tentei. ()async=>await new Completer().futurenão funciona porque usar aguardar é o mesmo que fazer new Completer().future.then(<continuation>), o que permite que o fechamento seja destruído no segundo Completer não é referenciado (o Completer mantém uma referência ao futuro de .future, o Future mantém uma referência à continuação como um fechamento).

Além disso, os Isolados (também conhecidos como threads) são limpos pelo GC, portanto, gerar um novo thread e interrompê-lo imediatamente ( import'dart:isolate';main(_)=>Isolate.spawn(main,0,paused:true);) não funciona. Mesmo gerando um Isolate com um loop infinito ( import'dart:isolate';f(_){while(true){print('x');}}main()=>Isolate.spawn(f,0);) mata o Isolate e sai do programa.

Ah bem.


se o seu programa principal continuasse executando e executando outras coisas, o coletor de lixo seria capaz de interromper o isolamento? Eu pergunto, porque o meu exemplo de goroutine parece semelhante ... eu assumi que o fato de o programa sair e devolver toda a memória ao sistema operacional não significa necessariamente que não vazou.
don bright

2

Rápido, 12 bytes

[3,5][0...0]

Explicação:

Esse é um vazamento de memória de fato que pode ocorrer em qualquer idioma, independentemente de o idioma usar gerenciamento manual de memória, contagem automática de referência (ARC, como Swift) ou até mesmo coleta de lixo abrangente.

[3,5]é apenas uma matriz literal. Essa matriz aloca memória suficiente para pelo menos esses dois elementos. O 3e 5são apenas arbitrários.

Subscrever (indexar) um Array<T>produz um ArraySlice<T>. An ArraySlice<T>é uma visão na memória da matriz da qual ela foi criada.

[3,5][0...0]produz um ArraySlice<Int>, cujo valor é [3]. Observe que 3nesta fatia é o mesmo 3elemento que 3o original Arraymostrado acima, não uma cópia.

A fatia resultante pode ser armazenada em uma variável e usada. A matriz original não é mais referenciada; portanto, você poderia pensar que poderia ser desalocada. No entanto, não pode.

Como a fatia expõe uma exibição na memória da matriz de onde veio, a matriz original deve ser mantida viva enquanto a fatia permanecer. Portanto, dos 2tamanhos de elementos originais de memória que foram alocados, apenas o primeiro tamanho de elemento de memória está sendo usado, sendo necessário que o outro exista para não alocar o primeiro. O segundo tamanho do elemento da memória é de fator vazado.

A solução para esse problema é não manter vivas pequenas fatias de matrizes grandes por muito tempo. Se você precisar persistir o conteúdo da fatia, promova-o para uma matriz, que acionará a memória a ser copiada, removendo a dependência da memória da matriz original:

Array([3,5][0...0])

2

Solução 1: C (Mac OS X x86_64), 109 bytes

A fonte do golf_sol1.c

main[]={142510920,2336753547,3505849471,284148040,2370322315,2314740852,1351437506,1208291319,914962059,195};

O programa acima precisa ser compilado com acesso de execução no segmento __DATA.

clang golf_sol1.c -o golf_sol1 -Xlinker -segprot -Xlinker __DATA -Xlinker rwx -Xlinker rwx

Em seguida, para executar o programa, execute o seguinte:

./golf_sol1 $(ruby -e 'puts "\xf5\xff\xff\xfe\xff\xff\x44\x82\x57\x7d\xff\x7f"')

Resultados:

Infelizmente, o Valgrind não observa a memória alocada nas chamadas do sistema, portanto, não consigo mostrar um vazamento detectado.

No entanto, podemos ver o vmmap para ver a grande parte da memória alocada (metadados MALLOC).

                                VIRTUAL   REGION 
REGION TYPE                        SIZE    COUNT (non-coalesced) 
===========                     =======  ======= 
Kernel Alloc Once                    4K        2 
MALLOC guard page                   16K        4 
MALLOC metadata                   16.2M        7 
MALLOC_SMALL                      8192K        2         see MALLOC ZONE table below
MALLOC_TINY                       1024K        2         see MALLOC ZONE table below
STACK GUARD                       56.0M        2 
Stack                             8192K        3 
VM_ALLOCATE (reserved)             520K        3         reserved VM address space (unallocated)
__DATA                             684K       42 
__LINKEDIT                        70.8M        4 
__TEXT                            5960K       44 
shared memory                        8K        3 
===========                     =======  ======= 
TOTAL                            167.0M      106 
TOTAL, minus reserved VM space   166.5M      106 

Explicação

Então, acho que preciso descrever o que realmente está acontecendo aqui, antes de avançar para a solução aprimorada.

Esta função principal está abusando da declaração de tipo ausente de C (portanto, o padrão é int, sem que seja necessário desperdiçar caracteres para escrevê-la), bem como o funcionamento dos símbolos. O vinculador se preocupa apenas com encontrar um símbolo chamado mainpara chamar. Então, aqui estamos fazendo principal uma matriz de int que estamos inicializando com nosso código de shell que será executado. Por isso, main não será adicionado ao segmento __TEXT, mas ao segmento __DATA, razão pela qual precisamos compilar o programa com um segmento __DATA executável.

O shellcode encontrado em main é o seguinte:

movq 8(%rsi), %rdi
movl (%rdi), %eax
movq 4(%rdi), %rdi
notl %eax
shrq $16, %rdi
movl (%rdi), %edi
leaq -0x8(%rsp), %rsi
movl %eax, %edx
leaq -9(%rax), %r10
syscall
movq (%rsi), %rsi
movl %esi, (%rsi)
ret

O que isso está fazendo é chamar a função syscall para alocar uma página de memória (o syscall mach_vm_allocate usa internamente). RAX deve ser igual a 0x100000a (informa ao syscall qual função queremos), enquanto o RDI mantém o destino da alocação (no nosso caso, queremos que seja mach_task_self ()), o RSI deve manter o endereço para gravar o ponteiro na memória recém-criada (portanto, estamos apenas apontando para uma seção da pilha), RDX mantém o tamanho da alocação (estamos passando RAX ou 0x100000a apenas para economizar em bytes), R10 mantém os sinalizadores (estamos indicando que pode seja alocado em qualquer lugar).

Agora não é óbvio de onde RAX e RDI estão obtendo seus valores. Sabemos que o RAX precisa ser 0x100000a e o RDI precisa ser o valor que mach_task_self () retorna. Felizmente, mach_task_self () é na verdade uma macro para uma variável (mach_task_self_), que está no mesmo endereço de memória todas as vezes (no entanto, deve mudar na reinicialização). Na minha instância específica, mach_task_self_ está localizado em 0x00007fff7d578244. Portanto, para reduzir as instruções, passaremos esses dados do argv. É por isso que rodamos o programa com esta expressão$(ruby -e 'puts "\xf5\xff\xff\xfe\xff\xff\x44\x82\x57\x7d\xff\x7f"')para o primeiro argumento. A string é os dois valores combinados, em que o valor RAX (0x100000a) é de apenas 32 bits e teve um complemento aplicado a ela (portanto, não há bytes nulos; apenas NÃO é o valor para obter o original), o próximo valor é o RDI (0x00007fff7d578244) que foi deslocado para a esquerda com 2 bytes extras de lixo eletrônico adicionados ao final (novamente para excluir os bytes nulos, basta voltar à direita para voltar ao original).

Após o syscall, estamos gravando em nossa memória recém-alocada. A razão para isso é porque a memória alocada usando mach_vm_allocate (ou este syscall) é na verdade páginas da VM e não é automaticamente paginada na memória. Em vez disso, eles são reservados até que os dados sejam gravados neles e, em seguida, essas páginas são mapeadas na memória. Não tinha certeza se atenderia aos requisitos se fosse reservado apenas.

Para a próxima solução, aproveitaremos o fato de que nosso código de shell não possui bytes nulos e, portanto, podemos movê-lo para fora do código de nosso programa para reduzir o tamanho.

Solução 2: C (Mac OS X x86_64), 44 bytes

A fonte para golf_sol2.c

main[]={141986632,10937,1032669184,2,42227};

O programa acima precisa ser compilado com acesso de execução no segmento __DATA.

clang golf_sol2.c -o golf_sol2 -Xlinker -segprot -Xlinker __DATA -Xlinker rwx -Xlinker rwx

Em seguida, para executar o programa, execute o seguinte:

./golf_sol2 $(ruby -e 'puts "\xb8\xf5\xff\xff\xfe\xf7\xd0\x48\xbf\xff\xff\x44\x82\x57\x7d\xff\x7f\x48\xc1\xef\x10\x8b\x3f\x48\x8d\x74\x24\xf8\x89\xc2\x4c\x8d\x50\xf7\x0f\x05\x48\x8b\x36\x89\x36\xc3"')

O resultado deve ser o mesmo de antes, pois estamos fazendo uma alocação do mesmo tamanho.

Explicação

Segue o mesmo conceito da solução 1, com a exceção de que movemos a parte do nosso código de vazamento para fora do programa.

O shellcode encontrado em main agora é o seguinte:

movq 8(%rsi), %rsi
movl $42, %ecx
leaq 2(%rip), %rdi
rep movsb (%rsi), (%rdi)

Isso basicamente copia o código de shell que passamos no argv para estar após esse código (então, depois de copiado, ele executará o código de shell inserido). O que funciona a nosso favor é que o segmento __DATA terá pelo menos um tamanho de página; portanto, mesmo que nosso código não seja tão grande, ainda podemos escrever com mais segurança. A desvantagem é a solução ideal aqui, nem precisaria da cópia; em vez disso, basta chamar e executar o código de shell diretamente no argv. Mas, infelizmente, essa memória não tem direitos de execução. Poderíamos alterar os direitos dessa memória, no entanto, exigiria mais código do que simplesmente copiá-lo. Uma estratégia alternativa seria alterar os direitos de um programa externo (mas mais sobre isso posteriormente).

O código de shell que passamos para o argv é o seguinte:

movl $0xfefffff5, %eax
notl %eax
movq $0x7fff7d578244ffff, %rdi
shrq $16, %rdi
movl (%rdi), %edi
leaq -0x8(%rsp), %rsi
movl %eax, %edx
leaq -9(%rax), %r10
syscall
movq (%rsi), %rsi
movl %esi, (%rsi)
ret

É o mesmo que o nosso código anterior, a única diferença é que estamos incluindo os valores para EAX e RDI diretamente.

Solução possível 1: C (Mac OS X x86_64), 11 bytes

A idéia de modificar o programa externamente, nos dá a possível solução de mover o vazador para um programa externo. Onde nosso programa atual (envio) é apenas um programa fictício, e o programa vazador alocará um pouco de memória em nosso programa de destino. Agora eu não tinha certeza se isso se enquadrava nas regras para esse desafio, mas mesmo assim é compartilhado.

Portanto, se usássemos mach_vm_allocate em um programa externo com a meta definida para o nosso programa de desafios, isso poderia significar que nosso programa de desafios precisaria ser algo como:

main=65259;

Onde esse código de shell é simplesmente um pequeno salto para si mesmo (salto / loop infinito), o programa permanece aberto e podemos fazer referência a um programa externo.

Solução possível 2: C (Mac OS X x86_64), 8 bytes

Curiosamente, quando eu estava olhando para a saída do valgrind, vi que, pelo menos de acordo com o valgrind, o dyld vazava memória. Tão eficazmente que todo programa está vazando alguma memória. Sendo esse o caso, poderíamos realmente criar um programa que não faz nada (simplesmente sai) e que realmente estará vazando memória.

Fonte:

main(){}


==55263== LEAK SUMMARY:
==55263==    definitely lost: 696 bytes in 17 blocks
==55263==    indirectly lost: 17,722 bytes in 128 blocks
==55263==      possibly lost: 0 bytes in 0 blocks
==55263==    still reachable: 0 bytes in 0 blocks
==55263==         suppressed: 16,316 bytes in 272 blocks

2

Inglês simples , 71 70 58 35 bytes

Removido 1 byte excluindo uma linha em branco. Foram removidos 12 bytes, eliminando a definição de tipo "bogon" e usando o tipo "coisa" pai em vez do subtipo "bogon". Foram removidos 23 bytes passando de um programa completo para apenas uma rotina que vaza memória.

Versão Golfed:

To x:
Allocate memory for a thing.

Versão não destruída que é um programa completo, usa uma definição de subtipo e não vaza memória:

A bogon is a thing.

To do something:
  Allocate memory for a bogon.
  Destroy the bogon.

To run:
  Start up.
  Do something.
  Shut down.

Se a versão em golf de "x" for chamada, ela vazará memória proporcionalmente ao número de vezes que "x" for chamada. Na versão para golfe, "Desaloque a coisa". corrigiria o vazamento de memória.

Por padrão, o inglês comum verifica vazamentos de memória. Quando a versão que vaza memória é executada, uma caixa de diálogo será exibida antes do encerramento do programa. A caixa de diálogo tem um título de "depuração", uma mensagem de "1 gotejamento" e um botão "OK". Quanto mais vezes a função de vazamento é chamada, maior o número de "gotas" na mensagem. Quando a versão que não vaza memória é executada, a caixa de diálogo não aparece.

Em inglês simples, uma "coisa" é um ponteiro para um item em uma lista duplamente vinculada. "Coisa", "iniciar" e "desligar" são definidas em um módulo chamado "o macarrão", que precisa ser copiado (geralmente como um arquivo separado) em cada projeto. "A", "o", "para", "alocar memória" e "destruir" são definidos no compilador.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.