Manipulação de memory de ponteiro QVector aninhada

Eu herdei um projeto substancial do Qt5, onde o vazamento acumulado de memory está se tornando um problema sério. (Sim, o memory leaks raramente deve ser tolerado, mas com restrições de tempo e orçamento da vida real …).

Esta GUI lê dados de imagem em objects de uma class de voxel, a serem exibidos graficamente. Os dados vêm do arquivo ou do buffer (se adquiridos ao vivo) e são armazenados como um qvector de ninho, ou seja:

QVector < QVector  > cVoxel; 

Quando uma imagem é lida do arquivo, o cVoxel é inicializado usando QVector.resize(0) .

 cVoxel.resize(0); 

Quando uma imagem salva no arquivo é aberta, um ponteiro Voxel local é criado e empurrado para o final do cVoxel , uma vez para cada pixel, fazendo o loop de todas as linhas e colunas:

 for (iRow = 0; iRow < nRows; ++iRow) { for (iCol = 0; iCol < nCols; ++iCol) { Voxel *v = new Voxel; cVoxel[iRow].push_back(v); // Code for reading data into cVoxel removed here ... } } 

Cortesia dos comentários úteis abaixo, eu já tive algum sucesso em ver a diminuição do uso de memory no Gerenciador de Tarefas do Windows, aninhando a destruição do cVoxel QVector no meu CTOR. Ao longo das linhas de:

 for (iRow = 0; iRow < nRows; iRow++) { for (iCol = 0; iCol < nCols; iCol++) { delete cVoxel[iRow][iCol]; } } 

Idealmente, uma grande reescrita é a melhor solução. Mas no mundo real, terei que tentar consertar os vazamentos maiores e esperar que isso seja suficiente até que haja resources suficientes disponíveis para uma solução mais ideal.

  • Eu olhei para vazamentos de memory em Voxel em si, mas não há nada óbvio lá.
  • Minha pesquisa revela que olhar para o Gerenciador de Tarefas do Windows para consumo de memory não é totalmente confiável (Win7 não é um sistema operacional em tempo real …), mas se abrir um arquivo aumenta o consumo de memory do aplicativo de 16M para 81,5M, então certamente deve haver alguma diminuição de memory se a memory alocada no cVoxel for liberada com sucesso? Se eu continuar abrindo e fechando as imagens, o consumo de memory do aplicativo continuará aumentando na mesma etapa. Nunca diminui depois de fechar qualquer / todas as imagens abertas.
  • No momento, não há nenhuma tentativa de liberar qualquer memory atribuída (usando o novo operador) ao cVoxel . Eu tentei algumas abordagens (e leia para saber mais), mas até agora pouca sorte.
  • QVector é excelente em cuidar do seu próprio manuseio de memory, mas eu estou preso com essa configuração ninho QVector, e simplesmente confiando em squeeze (), resize () ou similar de QVector apenas vazará memory (que já é o caso de outros variables ​​no projeto .. Eu corri o projeto através de Visual Leak Detector, então eu tenho uma idéia de quais são os culpados graves, e quais são os peixes pequenos)

—- EDITAR —-

Desculpas para o bagunçado ad-hod comentando abaixo, mas isso certamente está me ajudando a reduzir os vazamentos de memory (espera-se que a interrupção completa aconteça no devido tempo ..).

Eu editei na linha acima para (espero) tornar este post mais claro, e removi o meu melhor caso, já que ele não tinha nenhum impacto no memory leaks. As alterações significativas acima são os (2) breves parágrafos em itálico.

Eu também preciso investigar a sugestão relacionada ao @richardcitter (sp?) Polimorfismo.

— EDIT3 —

Removido Edit2, postou essa (nova) pergunta separadamente aqui .

Além disso, estou bastante confiante de que a resposta abaixo deve resolver essa questão – eu só preciso descobrir como usar o qvector.resize() ou encontrar uma solução alternativa para isso.

É difícil formatar código nos comentários, então eu adiciono isso como uma resposta, mesmo que isso não resolva seu problema. Também demorou bastante para um comentário de qualquer maneira.

Para resolver o comportamento indefinido e certificar-se de que você não precisa fazer nenhuma alocação extra, é possível pré-alocar o número de elementos nos vetores. Você já faz isso quando você chama resize(0) , mas ao invés de definir o tamanho que você realmente precisa, você faz o tamanho zero, você faz o vetor vazio.

Eu sugeriria algo assim em vez disso:

Primeiro use std::unique_ptr como sugerido por Richard Critten:

 QVector < QVector < std::unique_ptr  > > cVoxel; 

Se o Qt tiver seu próprio tipo de ponteiro exclusivo, você poderá usá-lo.

Então, quando você cria o que você usa resize para definir o tamanho real dos vetores:

 cVoxel.resize(nRows); 

Então você pode usar índices simples no vetor. Defina o tamanho dos vetores internos também:

 for (iRow = 0; iRow < nRows; ++iRow) { cVoxel[iRow].resize(nCols); // Resize to the number of columns for (iCol = 0; iCol < nCols; ++iCol) { cVoxel[iRow][iCol].reset(new Voxel); // Create the actual Voxel object // Code for reading data into cVoxel here ... } } 

Como você usa std::unique_ptr (ou o equivalente a Qt), a memory gerenciada pelo object std::unique_ptr será automaticamente liberada assim que o object for destruído. Portanto, não há mais vazamentos de memory, quando o vetor cVoxel sai do escopo ou é de outra forma destruído, assim seus objects Voxel estarão.

@SomeProgrammerDude: Você me deu 9/10 para a solução. Eu não sei se devo editar sua resposta ou usar isso, então o (s) moderador (es), por favor, edite de acordo.

Como descrito em um post do SO conectado , decidi contra os pointers inteligentes no final. A solução acima introduziu (para mim) a questão do compilador tentando referenciar uma function deletada. Caso contrário, está correto com algumas modificações:

 QVector < QVector  > cVoxel; 

Inicialização:

 cVoxel.resize(0); 

Atribuição de memory:

 { for (int i = 0; i < rows; ++i) { cVoxel.push_back( QVector  () ); for (int j = 0 ; j < cols ; ++j) { Voxel *v = new Voxel; cVoxel[i].push_back(v); } } } 

Finalmente DTOR liberando a memory:

  int iRow, iCol; for (iRow = 0; iRow < rows; iRow++) { for (iCol = 0; iCol < cols; iCol++) { delete cVoxel[iRow][iCol]; } }