Encontrando referências cíclicas boost :: shared_ptr
-
18-09-2019 - |
Pergunta
Existe alguma dica / truques para encontrar referências cíclicas de shared_ptr de?
Este é um exmaple do que eu estou tentando encontrar -. Infelizmente eu não consigo encontrar o loop no meu código
struct A
{
boost::shared_ptr<C> anC;
};
struct B
{
boost::shared_ptr<A> anA;
};
struct C
{
boost::shared_ptr<B> anB;
};
Solução 4
Eu usei uma combinação das mensagens acima. Eu usei um profiler de memória, veio com alguns ciclos suspeitos e quebrou aqueles usando weak_ptr do.
Eu usei o construído em detecção de vazamento de memória CRT antes, mas, infelizmente, no meu caso há vários singletons estáticos que não entendo desalocada até módulo de descarga que eu acredito que é após os detectores CRT ciclo de vida. Basicamente, ele dá um monte de vômito que são falsos positivos.
Outras dicas
Eu recomendo usar Valgrind . Quando encerrar o processo, ele vai mostrar toda a memória vazada. A menos que seu desligamento alguma maneira quebra o ciclo, quaisquer ciclos deve aparecer como memória vazada e Valgrind vai lhe dizer onde em seu código a memória foi originalmente atribuído a partir.
Eu estava encarregado do projeto de um sistema de risco de crédito uma vez (em C ++, no entanto, que não é relevante). Essas coisas são realmente grandes gráficos com risco alocado nos nós. Tivemos uma heurística simples para descobrir se estávamos em um ciclo - se percorrido mais de 500 vezes (I esquecer o número exato - era configurável), a resposta foi sim. A maioria dos esquemas de detecção ciclo de confiar em heurísticas como este.
Eu tive problemas semelhantes no passado -. Vazamentos de memória devido à shared_ptr referências cíclicas que foi detectado durante meses
Cuidado com os "caches". Eu tenho um objeto (chamado de Let It "Factory") que movimentou os itens ( "widgets"). Widgets tinha a propriedade de ser A) Imutável, e B) Tinha um shared_ptr<Factory>
ao seu criador (por vezes criados outros widgets, etc). Tudo funcionou bem, até que eu adicionei um cache Widget para Factory - uma vez que os Widgets eram imutáveis, fazia sentido para armazenar em cache-los, para devolver o mesmo toda vez Widget foram solicitadas. Meu cache era um esconderijo de shared_ptr<Widget>
, de modo instantâneo vazamento em silêncio. As correções são óbvias, então eu não vou entrar em-los.
Em última análise, eu era capaz de inclinar-se sobre a plataforma que eu estava usando para detectar tais vazamentos de memória do CRT. CRT do Visual Studio tem memória vazada detecção e reporte, que eu habilitado no meu programa de teste para evitar regressões:
int main()
{
// code code code
// code code code
#ifdef _MSC_VER
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
_CrtDumpMemoryLeaks();
#endif
}
GCC provavelmente tem relatórios de vazamento básica similar, mas eu não sei o que é.
Eu acho que a resposta mais simples é que há somente tanto ponteiros inteligentes pode fazer por você:
Eu sugiro gravação sempre que você make um loop, (fácil se você criar todos os três objetos de uma só vez, mais complicado caso contrário ...), e depois verificar que o registro onde você excluir / objetos desvincular, ou apenas periodicamente se isso não é possível.
Você poderia implementar algum tipo de depuração interface que retorna uma lista de shared_ptrs pertencentes a este objeto. Você precisaria fazer isso para todas as classes armazenadas em um shared_ptr. Agora você tem um gráfico genérico que você pode percorrer, e pode usar algoritmos de detecção de ciclo nele. Acredito Tarjan está fortemente ligado algoritmo componente trabalho poder para isso, mas a teoria dos grafos não é o meu forte.