Esta é a versão 8.3.0 (desenvolvimento da próxima versão) de um coletor de lixo conservador para C e C++.
Licença: estilo MIT
Você pode encontrar uma versão mais recente/estável na página de download ou no site BDWGC.
Além disso, as últimas correções de bugs e novos recursos estão disponíveis no repositório de desenvolvimento.
Este destina-se a ser um alocador de armazenamento de coleta de lixo de uso geral. Os algoritmos usados são descritos em:
Boehm, H. e M. Weiser, "Coleta de lixo em um ambiente não cooperativo", Software Practice & Experience, setembro de 1988, pp.
Boehm, H., A. Demers e S. Shenker, "Mostly Parallel Garbage Collection", Anais da Conferência ACM SIGPLAN '91 sobre Design e Implementação de Linguagem de Programação, SIGPLAN Notices 26, 6 (junho de 1991), pp. 164.
Boehm, H., "Space Efficient Conservative Garbage Collection", Anais da Conferência ACM SIGPLAN '91 sobre Design e Implementação de Linguagem de Programação, SIGPLAN Notices 28, 6 (junho de 1993), pp.
Boehm H., "Reduzindo perdas de cache do coletor de lixo", Anais do Simpósio Internacional de Gerenciamento de Memória de 2000.
Possíveis interações entre o coletor e os compiladores de otimização são discutidas em
Boehm, H. e D. Chase, "A Proposal for GC-safe C Compilation", The Journal of C Language Translation 4, 2 (dezembro de 1992).
Boehm H., "Simple GC-safe Compilation", Anais da Conferência ACM SIGPLAN '96 sobre Design e Implementação de Linguagem de Programação.
Diferentemente do coletor descrito na segunda referência, este coletor opera com o mutador parado durante toda a coleta (padrão) ou de forma incremental durante as alocações. (Este último é suportado em menos máquinas.) Nas plataformas mais comuns, pode ser construído com ou sem suporte a threads. Em algumas plataformas, pode tirar proveito de um multiprocessador para acelerar a coleta de lixo.
Muitas das ideias subjacentes ao colecionador já foram exploradas por outros. Notavelmente, alguns dos sistemas de tempo de execução desenvolvidos na Xerox PARC no início da década de 1980 examinaram conservadoramente pilhas de threads para localizar possíveis ponteiros (cf. Paul Rovner, "On Adding Garbage Collection and Runtime Types to a Strongly-Typed Stastaticly Checked, Concurrent Language" Xerox PARC CSL 84-7). Doug McIlroy escreveu um coletor mais simples e totalmente conservador que fazia parte da versão 8 do UNIX (tm), mas parece não ter sido amplamente utilizado.
Estão incluídas ferramentas rudimentares para uso do coletor como detector de vazamento, assim como um pacote de cordas bastante sofisticado "cordão" que faz uso do coletor. (Ver README.cords e H.-J. Boehm, R. Atkinson e M. Plass, "Ropes: An Alternative to Strings", Software Practice and Experience 25, 12 (dezembro de 1995), pp. 1315-1330. Este é muito semelhante ao pacote "rope" no Xerox Cedar, ou ao pacote "rope" no SGI STL ou na distribuição g++.)
Documentação adicional do coletor pode ser encontrada na visão geral.
Alguns dos usos conhecidos do coletor estão listados na página Clientes conhecidos do GitHub.
Este é um alocador de armazenamento de coleta de lixo que se destina a ser usado como um plug-in substituto para o malloc de C.
Como o coletor não exige que os ponteiros sejam marcados, ele não tenta garantir que todo o armazenamento inacessível seja recuperado. No entanto, em nossa experiência, normalmente é mais bem-sucedido na recuperação de memória não utilizada do que a maioria dos programas C que usam desalocação explícita. Ao contrário dos vazamentos introduzidos manualmente, a quantidade de memória não recuperada normalmente permanece limitada.
A seguir, um "objeto" é definido como uma região de memória alocada pelas rotinas descritas abaixo.
Quaisquer objetos não destinados a serem coletados devem ser apontados a partir de outros objetos acessíveis ou dos registros, pilha, dados ou segmentos bss alocados estaticamente. Os ponteiros da pilha ou dos registradores podem apontar para qualquer lugar dentro de um objeto. O mesmo é verdadeiro para ponteiros de heap se o coletor for compilado com ALL_INTERIOR_POINTERS
definido, ou GC_all_interior_pointers
estiver definido, como agora é o padrão.
Compilar sem ALL_INTERIOR_POINTERS
pode reduzir a retenção acidental de objetos inúteis, exigindo ponteiros do heap para o início de um objeto. Mas isto já não parece ser um problema significativo para a maioria dos programas que ocupam uma pequena fração do espaço de endereço possível.
Existem várias rotinas que modificam o algoritmo de reconhecimento de ponteiro. GC_register_displacement
permite que certos ponteiros interiores sejam reconhecidos mesmo que ALL_INTERIOR_POINTERS
não esteja definido. GC_malloc_ignore_off_page
permite que alguns ponteiros no meio de objetos grandes sejam desconsiderados, reduzindo bastante a probabilidade de retenção acidental de objetos grandes. Para a maioria dos propósitos, parece melhor compilar com ALL_INTERIOR_POINTERS
e usar GC_malloc_ignore_off_page
se você receber avisos do coletor de alocações de objetos muito grandes. Veja aqui para detalhes.
AVISO : ponteiros dentro da memória alocada pelo malloc
padrão (sistema) não são vistos pelo coletor de lixo. Assim, os objetos apontados apenas para essa região podem ser desalocados prematuramente. Sugere-se, portanto, que o malloc
padrão seja usado apenas para regiões de memória, como buffers de E/S, que garantem não conter ponteiros para memória colecionável de lixo. Ponteiros em variáveis automáticas, estáticas ou de registro da linguagem C são reconhecidos corretamente. (Observe que GC_malloc_uncollectable
possui semântica semelhante ao malloc padrão, mas aloca objetos que são rastreados pelo coletor.)
AVISO : o coletor nem sempre sabe encontrar ponteiros em áreas de dados associadas a bibliotecas dinâmicas. Isso é fácil de resolver se você souber como encontrar essas áreas de dados em seu sistema operacional (consulte GC_add_roots
). O código para fazer isso no SunOS, IRIX 5.X e 6.X, HP/UX, Alpha OSF/1, Linux e Win32 está incluído e é usado por padrão. (Consulte README.win32 e README.win64 para obter detalhes do Windows.) Em outros sistemas, os ponteiros das áreas de dados da biblioteca dinâmica podem não ser considerados pelo coletor. Se você estiver escrevendo um programa que depende do coletor que varre áreas de dados da biblioteca dinâmica, pode ser uma boa ideia incluir pelo menos uma chamada para GC_is_visible
para garantir que essas áreas estejam visíveis para o coletor.
Observe que o coletor de lixo não precisa ser informado sobre dados somente leitura compartilhados. No entanto, se o mecanismo de biblioteca compartilhada puder introduzir áreas de dados descontíguas que possam conter ponteiros, o coletor precisará ser informado.
O processamento de sinais para a maioria dos sinais pode ser adiado durante a coleta e durante partes ininterruptas do processo de alocação. Como os mallocs ANSI C padrão, por padrão não é seguro invocar malloc (e outras rotinas de GC) a partir de um manipulador de sinal enquanto outra chamada de malloc pode estar em andamento.
O alocador/coletor também pode ser configurado para operação thread-safe. (A segurança total do sinal também pode ser alcançada, mas apenas ao custo de duas chamadas de sistema por malloc, o que geralmente é inaceitável.)
AVISO : o coletor não garante a varredura do armazenamento local do thread (por exemplo, do tipo acessado com pthread_getspecific
). O coletor verifica as pilhas de threads, portanto, geralmente a melhor solução é garantir que quaisquer ponteiros armazenados no armazenamento local do thread também sejam armazenados na pilha do thread durante sua vida útil. (Este é sem dúvida um bug antigo, mas ainda não foi corrigido.)
Existem várias maneiras de construir o coletor:
CMake (é a forma recomendada)
GNU autoconf/automake
Zig (experimental)
MS nmake (diretamente)
Makefile.direct
Compilação C manual
A maneira mais simples de construir a libgc (assim como a libcord) e executar os testes usando cmake:
saída mkdir cmake -Dbuild_tests=ON.. cmake --build.ctest
Esta é a forma mais multiplataforma de construir a biblioteca. Consulte README.cmake para obter detalhes.
Observe que o repositório de origem do coletor não contém arquivos configure
e gerados automaticamente semelhantes, portanto, o procedimento completo de construção do coletor baseado em autoconf do repositório de origem poderia ser semelhante a:
./autogen.sh ./configure fazer verificação
O processo de construção no estilo GNU compreende os alvos e opções usuais. make install
instala libgc e libcord. Tente ./configure --help
para ver todas as opções de configuração. Atualmente não é possível exercer todas as combinações de opções de construção desta forma.
Consulte README.autoconf para obter detalhes.
Construir e testar o coletor usando zig é simples em sua forma mais simples:
teste de construção zig
É possível configurar a construção através do uso de variáveis, por exemplo, zig build -Denable_redirect_malloc -Denable_threads=false
. Zig oferece excelente funcionalidade de compilação cruzada, é configurável assim:
compilação zig -Dtarget=riscv64-linux-musl
Atualmente, é necessária uma versão noturna do zig 0.12, que pode ser baixada em https://ziglang.org/download/
No Windows, supondo que as ferramentas de construção da Microsoft estejam instaladas e configuradas adequadamente, é possível construir a biblioteca e executar os testes usando nmake
diretamente, por exemplo, digitando nmake -f NT_MAKEFILE check
. No entanto, a forma recomendada é usar cmake conforme descrito acima.
Consulte README.win32 para obter detalhes.
Para o processo de construção baseado em makefile de estilo antigo (clássico), digitar make -f Makefile.direct check
criará automaticamente libgc, libcord e, em seguida, executará vários testes, como gctest
. O teste é um teste um tanto superficial da funcionalidade do coletor. A falha é indicada por um core dump ou por uma mensagem informando que o coletor está quebrado. gctest
pode levar alguns segundos para ser executado em desktops vintage de 64 bits razoáveis de 2023. Pode usar até cerca de 30 MB de memória.
Makefile.direct irá gerar uma biblioteca libgc.a à qual você deve vincular.
Finalmente, na maioria dos destinos, o coletor poderia ser construído e testado diretamente com uma única invocação do compilador, como esta (o exemplo não possui suporte multi-threading):
cc -I include -o gctest testes/gctest.c extra/gc.c && ./gctest
Por exemplo, isso pode ser conveniente para fins de depuração.
A biblioteca pode ser configurada com mais precisão durante a construção, definindo as macros listadas no arquivo README.macros.
A biblioteca é construída com suporte a threads habilitado (ou seja, para operação thread-safe) por padrão, a menos que seja explicitamente desabilitado por:
-Denable_threads=false
opção passada para cmake
ou zig build
Opção --disable-threads
passada para ./configure
O coletor opera silenciosamente na configuração padrão. No caso de problemas, isso geralmente pode ser alterado definindo as variáveis de ambiente GC_PRINT_STATS
ou GC_PRINT_VERBOSE_STATS
. Isso resultará em algumas linhas de saída descritiva para cada coleção. (As estatísticas fornecidas apresentam algumas peculiaridades. As coisas não parecem somar por vários motivos, principalmente perdas de fragmentação. Elas são provavelmente muito mais significativas para o programa gctest
planejado do que para seu aplicativo.)
O uso (clonagem) de libatomic_ops
agora é opcional, desde que o compilador suporte intrínsecos atômicos. A maioria dos compiladores modernos faz isso. A exceção notável é o compilador MS (a partir do Visual Studio 2022).
Se necessário, a maioria das distribuições de SO possui o pacote libatomic_ops
; alternativamente, você pode baixá-lo ou cloná-lo no espaço https://github.com/ivmai/libatomic_ops.
O coletor atualmente foi projetado para funcionar essencialmente sem modificações em máquinas que usam um espaço de endereço plano de 32 ou 64 bits. Isso inclui a grande maioria das estações de trabalho e PCs x86 (i386 ou posterior).
Em alguns casos (por exemplo, OS/2, Win32) um makefile separado é fornecido; eles têm um arquivo docs/platforms/README.* específico do host separado.
Bibliotecas dinâmicas são totalmente suportadas apenas em SunOS/Solaris (e mesmo esse suporte não é funcional na última versão Sun 3), Linux, FreeBSD, NetBSD, IRIX, HP/UX, Win32 (não win32s) e OSF/1 em DEC Máquinas AXP e talvez algumas outras listadas no topo de dyn_load.c. Em outras máquinas, recomendamos que você faça o seguinte:
Adicione suporte a biblioteca dinâmica (e envie-nos o código).
Use versões estáticas das bibliotecas.
Providencie bibliotecas dinâmicas para usar o malloc padrão. Isso ainda é perigoso se a biblioteca armazenar um ponteiro para um objeto coletado como lixo. Mas quase todas as interfaces padrão proíbem isso, porque lidam corretamente com ponteiros para empilhar objetos alocados. ( strtok
é uma exceção. Não use.)
Em todos os casos, assumimos que o alinhamento do ponteiro é consistente com aquele imposto pelos compiladores C padrão. Se você usar um compilador não padrão, talvez seja necessário ajustar os parâmetros de alinhamento definidos em include/private/gc_priv.h
. Observe que isso também pode ser um problema com registros/estruturas compactadas, se eles imporem menos alinhamento para ponteiros.
Uma porta para uma máquina que não tenha endereço de byte ou que não use endereços de 32 ou 64 bits exigirá um grande esforço. Uma porta para MSDOS ou win16 simples é difícil.
Para máquinas ainda não mencionadas, ou para compiladores fora do padrão, algumas sugestões de portabilidade são fornecidas aqui.
As rotinas a seguir devem ser chamadas diretamente pelo usuário. Observe que normalmente apenas GC_malloc
é necessário. As chamadas GC_clear_roots
e GC_add_roots
podem ser necessárias se o coletor tiver que rastrear a partir de locais não padronizados (por exemplo, de áreas de dados de biblioteca dinâmica em uma máquina na qual o coletor ainda não os entende). Em algumas máquinas, pode ser desejável definir GC_stackbottom
como uma boa aproximação da base da pilha (parte inferior).
O código do cliente pode incluir gc.h
, que define todos os itens a seguir, além de muitos outros.
GC_malloc(bytes)
- Aloca um objeto de um determinado tamanho. Ao contrário do malloc, o objeto é limpo antes de ser devolvido ao usuário. GC_malloc
invocará o coletor de lixo quando determinar que isso é apropriado. GC_malloc poderá retornar 0 se não conseguir adquirir espaço suficiente do sistema operacional. Esta é a consequência mais provável da falta de espaço. Outras consequências possíveis são que uma chamada de função falhará devido à falta de espaço na pilha, ou que o coletor falhará de outras maneiras porque não consegue manter suas estruturas de dados internas, ou que um processo crucial do sistema falhará e derrubará a máquina. A maioria dessas possibilidades é independente da implementação do malloc.
GC_malloc_atomic(bytes)
- Aloca um objeto de um determinado tamanho que não contém nenhum ponteiro. Não é garantido que o objeto retornado seja limpo. (Sempre pode ser substituído por GC_malloc
, mas resulta em tempos de coleta mais rápidos. O coletor provavelmente será executado mais rápido se grandes matrizes de caracteres, etc. forem alocadas com GC_malloc_atomic
do que se forem alocadas estaticamente.)
GC_realloc(object, new_bytes)
- Altere o tamanho do objeto para um determinado tamanho. Retorna um ponteiro para o novo objeto, que pode ou não ser igual ao ponteiro para o objeto antigo. O novo objeto é considerado atômico se e somente se o antigo o fosse. Se o novo objeto for composto e maior que o objeto original, os bytes recém-adicionados serão limpos. É muito provável que isso aloque um novo objeto.
GC_free(object)
- Desaloca explicitamente um objeto retornado por GC_malloc
ou GC_malloc_atomic
ou amigos. Não é necessário, mas pode ser usado para minimizar coletas se o desempenho for crítico. Provavelmente uma perda de desempenho para objetos muito pequenos (<= 8 bytes).
GC_expand_hp(bytes)
– Aumenta explicitamente o tamanho do heap. (Isso normalmente é feito automaticamente se uma coleta de lixo não conseguiu recuperar memória suficiente. Chamadas explícitas para GC_expand_hp
podem impedir coletas desnecessariamente frequentes na inicialização do programa.)
GC_malloc_ignore_off_page(bytes)
- Idêntico a GC_malloc
, mas o cliente promete manter um ponteiro para algum lugar dentro do primeiro bloco de heap GC (512 .. 4096 bytes ou até mais, dependendo da configuração) do objeto enquanto ele estiver ativo. (Este ponteiro normalmente deve ser declarado volátil para evitar interferência de otimizações do compilador.) Esta é a maneira recomendada de alocar qualquer coisa que provavelmente seja maior que 100 KB ou mais. ( GC_malloc
pode resultar em falha na recuperação de tais objetos.)
GC_set_warn_proc(proc)
– Pode ser usado para redirecionar avisos do coletor. Tais avisos devem ser raros e não devem ser ignorados durante o desenvolvimento do código.
GC_enable_incremental()
– Habilita coleta geracional e incremental. Útil para grandes pilhas em máquinas que fornecem acesso a informações sujas de páginas. Algumas implementações de bits sujos podem interferir na depuração (capturando falhas de endereço) e colocar restrições em argumentos de heap para chamadas de sistema (uma vez que falhas de gravação dentro de uma chamada de sistema podem não ser bem tratadas).
GC_register_finalizer(object, proc, data, 0, 0)
e amigos - Permite o registro do código de finalização. O código de finalização fornecido pelo usuário ( (*proc)(object, data)
) é invocado depois que o objeto se torna inacessível. Para usos mais sofisticados e para problemas de pedido de finalização, consulte gc.h
.
A variável global GC_free_space_divisor
pode ser ajustada para cima em relação ao seu valor padrão de 3 para usar menos espaço e mais tempo de coleta, ou para baixo para o efeito oposto. Configurá-lo como 1 quase desabilitará as coleções e fará com que todas as alocações simplesmente aumentem o heap.
A variável GC_non_gc_bytes
, que normalmente é 0, pode ser alterada para refletir a quantidade de memória alocada pelas rotinas acima que não deve ser considerada candidata à coleta. O uso descuidado pode, obviamente, resultar em consumo excessivo de memória.
Alguns ajustes adicionais são possíveis através dos parâmetros definidos perto do topo de include/private/gc_priv.h
.
Se apenas GC_malloc
for usado, pode ser apropriado definir:
#define malloc(n) GC_malloc(n) #define calloc(m,n) GC_malloc((m)*(n))
Para pequenos pedaços de código MUITO intensivo de alocação, gc_inline.h
inclui algumas macros de alocação que podem ser usadas no lugar de GC_malloc
e amigos.
Todos os nomes visíveis externamente no coletor de lixo começam com GC_
. Para evitar conflitos de nomes, o código do cliente deve evitar esse prefixo, exceto ao acessar rotinas do coletor de lixo.
Existem disposições para alocação com informações de tipo explícitas. Isso raramente é necessário. Detalhes podem ser encontrados em gc_typed.h
.
A interface Ellis-Hull C++ para o coletor está incluída na distribuição do coletor. Se você pretende usar isso, digite ./configure --enable-cplusplus && make
(ou cmake -Denable_cplusplus=ON . && cmake --build .
ou make -f Makefile.direct c++
dependendo do sistema de compilação que você usa). Isso cria arquivos libgccpp.a e libgctba.a, ou seus equivalentes de biblioteca compartilhada (libgccpp.so e libgctba.so). Você deve vincular o primeiro (gccpp) ou o segundo (gctba), mas não ambos. Veja gc_cpp.h
e aqui para a definição da interface. Esta interface tenta aproximar a proposta de coleta de lixo C++ de Ellis-Detlefs sem alterações no compilador.
Muitas vezes também será necessário usar gc_allocator.h
e o alocador ali declarado para construir estruturas de dados STL. Caso contrário, os subobjetos das estruturas de dados STL serão alocados usando um alocador de sistema e os objetos aos quais eles se referem poderão ser coletados prematuramente.
O coletor pode ser usado para rastrear vazamentos em programas C que se destinam a rodar com malloc/free (por exemplo, código com restrições extremas de tempo real ou de portabilidade). Para fazer isso defina FIND_LEAK
no Makefile. Isso fará com que o coletor imprima uma descrição do objeto legível por humanos sempre que for encontrado um objeto inacessível que não tenha sido explicitamente liberado. Esses objetos também serão recuperados automaticamente.
Se todos os objetos forem alocados com GC_DEBUG_MALLOC
(veja a próxima seção), então, por padrão, a descrição do objeto legível conterá pelo menos o arquivo de origem e o número da linha na qual o objeto vazado foi alocado. Às vezes, isso pode ser suficiente. (Em algumas máquinas, ele também reportará um rastreamento de pilha enigmático. Se isso não for simbólico, às vezes pode ser chamado para um rastreamento de pilha simbólico invocando o programa "foo" com tools/callprocs.sh foo
. É um shell curto script que invoca adb para expandir os valores do contador do programa para endereços simbólicos. Foi amplamente fornecido por Scott Schwartz.)
Observe que os recursos de depuração descritos na próxima seção podem às vezes ser um pouco menos eficazes no modo de localização de vazamentos, já que neste último GC_debug_free
na verdade resulta na reutilização do objeto. (Caso contrário, o objeto será simplesmente marcado como inválido.) Além disso, observe que a maioria dos testes de GC não são projetados para serem executados de forma significativa no modo FIND_LEAK
.
As rotinas GC_debug_malloc
, GC_debug_malloc_atomic
, GC_debug_realloc
e GC_debug_free
fornecem uma interface alternativa para o coletor, que fornece alguma ajuda com erros de substituição de memória e similares. Os objetos alocados desta forma são anotados com informações adicionais. Algumas dessas informações são verificadas durante a coleta de lixo e as inconsistências detectadas são relatadas ao stderr.
Casos simples de gravação após o final de um objeto alocado devem ser capturados se o objeto for explicitamente desalocado ou se o coletor for invocado enquanto o objeto estiver ativo. A primeira desalocação de um objeto limpará as informações de depuração associadas a um objeto, portanto, chamadas repetidas acidentalmente para GC_debug_free
reportarão a desalocação de um objeto sem informações de depuração. Erros de falta de memória serão relatados ao stderr, além de retornar NULL
.
A verificação GC_debug_malloc
durante a coleta de lixo é habilitada com a primeira chamada para esta função. Isso resultará em alguma lentidão durante as coletas. Se forem desejadas verificações freqüentes de heap, isso pode ser conseguido invocando explicitamente GC_gcollect
, por exemplo, a partir do depurador.
Os objetos alocados em GC_debug_malloc
não devem ser passados para GC_realloc
ou GC_free
e vice-versa. No entanto, é aceitável alocar apenas alguns objetos com GC_debug_malloc
e usar GC_malloc
para outros objetos, desde que os dois pools sejam mantidos distintos. Nesse caso, há uma probabilidade muito baixa de que os objetos alocados GC_malloc
possam ser identificados incorretamente como tendo sido sobrescritos. Isso deve acontecer com probabilidade de no máximo um em 2**32. Esta probabilidade é zero se GC_debug_malloc
nunca for chamado.
GC_debug_malloc
, GC_debug_malloc_atomic
e GC_debug_realloc
recebem dois argumentos adicionais, uma string e um número inteiro. Eles não são interpretados pelo alocador. Eles são armazenados no objeto (a string não é copiada). Caso seja detectado algum erro envolvendo o objeto, eles serão impressos.
As macros GC_MALLOC
, GC_MALLOC_ATOMIC
, GC_REALLOC
, GC_FREE
, GC_REGISTER_FINALIZER
e amigos também são fornecidas. Eles exigem os mesmos argumentos que as rotinas correspondentes (sem depuração). Se gc.h
estiver incluído com GC_DEBUG
definido, eles chamam as versões de depuração dessas funções, passando o nome do arquivo atual e o número da linha como os dois argumentos extras, quando apropriado. Se gc.h
for incluído sem GC_DEBUG
definido, todas essas macros serão definidas para seus equivalentes não depurados. ( GC_REGISTER_FINALIZER
é necessário, pois os ponteiros para objetos com informações de depuração são, na verdade, ponteiros para um deslocamento de 16 bytes do início do objeto, e alguma tradução é necessária quando as rotinas de finalização são invocadas. Para obter detalhes sobre o que está armazenado no cabeçalho, consulte a definição do tipo oh no arquivo dbg_mlc.c.)
O coletor normalmente interrompe o código do cliente durante uma fase de marcação de coleta de lixo. Isto pode ser inaceitável se for necessária uma resposta interativa para programas com grandes pilhas. O coletor também pode ser executado em modo "geracional", no qual geralmente tenta coletar apenas objetos alocados desde a última coleta de lixo. Além disso, neste modo, as coletas de lixo são executadas principalmente de forma incremental, com uma pequena quantidade de trabalho executada em resposta a cada um de um grande número de solicitações GC_malloc
.
Este modo é habilitado por uma chamada para GC_enable_incremental
.
A coleta incremental e geracional só é eficaz na redução dos tempos de pausa se o coletor tiver alguma maneira de saber quais objetos ou páginas foram modificados recentemente. O coletor usa duas fontes de informação:
Informações fornecidas pelo sistema VM. Isto pode ser fornecido de várias formas. No Solaris 2.X (e potencialmente em outros sistemas similares), as informações sobre páginas sujas podem ser lidas no sistema de arquivos /proc. Em outros sistemas (por exemplo, SunOS4.X) é possível proteger o heap contra gravação e detectar as falhas resultantes. Nesses sistemas, exigimos que as chamadas do sistema gravadas no heap (diferentes de leitura) sejam tratadas especialmente pelo código do cliente. Consulte os_dep.c
para obter detalhes.
Informações fornecidas pelo programador. O objeto é considerado sujo após uma chamada para GC_end_stubborn_change
desde que a biblioteca tenha sido compilada adequadamente. Normalmente não vale a pena usá-lo para objetos de vida curta. Observe que bugs causados por uma chamada GC_end_stubborn_change
ou GC_reachable_here
ausente provavelmente serão observados com pouca frequência e difíceis de rastrear.
Qualquer memória que não tenha um ponteiro reconhecível será recuperada. Exclusivo ou links para frente e para trás em uma lista não é o suficiente.
Alguns otimizadores C podem perder o último ponteiro indisfarçável para um objeto de memória como consequência de otimizações inteligentes. Isso quase nunca foi observado na prática.
Este não é um coletor em tempo real. Na configuração padrão, a porcentagem de tempo necessária para a coleta deve ser constante em todos os tamanhos de heap. Mas as pausas na coleta aumentarão para pilhas maiores. Eles diminuirão com o número de processadores se a marcação paralela estiver habilitada.
(Em máquinas antigas de 2007, os tempos de GC podem ser da ordem de 5 ms por MB de memória acessível que precisa ser verificada e processada. Sua milhagem pode variar.) O recurso de coleta incremental/geracional pode ajudar em alguns casos.
Por favor, aborde relatórios de bugs e novas ideias de recursos para problemas do GitHub. Antes de enviar, verifique se o mesmo ainda não foi feito por outra pessoa.
Se você quiser contribuir, envie uma solicitação pull ao GitHub. Processe os arquivos modificados com formato clang antes do envio.
Se precisar de ajuda, use Stack Overflow. Discussões técnicas mais antigas estão disponíveis no arquivo da lista de discussão bdwgc
- ele pode ser baixado como um arquivo compactado ou navegado em Narkive.
Para receber anúncios de novos lançamentos, assine o feed RSS. (Para receber notificações por e-mail, um serviço gratuito de terceiros, como o IFTTT RSS Feed, pode ser configurado.) Para ser notificado sobre todos os problemas, assista ao projeto no GitHub.
Nossa intenção é facilitar o uso do bdwgc (libgc), tanto em software livre quanto em software proprietário. Conseqüentemente, o código conservador do coletor de lixo Boehm-Demers-Weiser que esperamos que seja vinculado dinamicamente ou estaticamente a um aplicativo cliente é coberto por uma licença própria, que é semelhante em espírito a uma licença do estilo MIT.
As informações exatas de licenciamento são fornecidas no arquivo LICENSE.
Todos os contribuidores estão listados no arquivo AUTHORS.