Como encontrar uma fuga de memória num código/projecto c++?

sou um programador de C++ na plataforma Windows. Estou a usar o Visual Studio 2008.

Costumo acabar no código com fugas de memória.

Normalmente encontro a fuga de memória ao inspeccionar o código, mas é complicado e nem sempre é uma boa abordagem.

Como não posso pagar uma ferramenta de detecção de fugas de memória, queria que sugerissem as melhores formas possíveis de evitar fugas de memória.

    Quero saber como o programador Encontra a memória. fuga. Há algum padrão ou procedimento a seguir para garantir que não há fuga de memória no programa?
Author: Alex, 2011-06-07

18 answers

Instruções

Coisas que vais precisar

  • proficiência em C++
  • compilador C++
  • depurador e outras ferramentas de software de investigação

1

Compreender o básico do operador. O operador de c++ " new " aloca memória heap. O operador" delete " liberta memória de heap. Para cada "novo", você deve usar um "delete" para que você livre a mesma memória que você alocou:

char* str = new char [30]; // Allocate 30 bytes to house a string.

delete [] str; // Clear those 30 bytes and make str point nowhere.

2

Realocar a memória apenas se tiver excluir. No código abaixo, str adquire um novo endereço com a segunda alocação. O primeiro endereço está perdido irremediavelmente, assim como os 30 bytes que ele apontou. Agora são impossíveis de libertar, E tu tens uma fuga de memória.

char* str = new char [30]; // Give str a memory address.

// delete [] str; // Remove the first comment marking in this line to correct.

str = new char [60]; /* Give str another memory address with
                                                    the first one gone forever.*/

delete [] str; // This deletes the 60 bytes, not just the first 30.

3

Cuidado com os apontadores. Cada variável dinâmica (memória alocada no heap) precisa ser associada com um ponteiro. Quando uma variável dinâmica se desassocia do(s) Seu (s) ponteiro (s), torna-se impossível apagar. Mais uma vez, isto resulta numa fuga de memória:
char* str1 = new char [30];

char* str2 = new char [40];

strcpy(str1, "Memory leak");

str2 = str1; // Bad! Now the 40 bytes are impossible to free.

delete [] str2; // This deletes the 30 bytes.

delete [] str1; // Possible access violation. What a disaster!

4

Cuidado com as indicações locais. Um ponteiro que você declara em uma função é alocado na pilha, mas a variável dinâmica para a qual ele aponta é alocada no heap. Se não o apagar, irá persistir após o programa sair da função:
void Leak(int x){

char* p = new char [x];

// delete [] p; // Remove the first comment marking to correct.

}

5

Presta atenção ao aparelho quadrado depois de "apagar"."Use" delete " por si só para libertar um único objeto. Use "delete" [] com parêntesis rectos para libertar uma lista de heap. Nao faça algo assim:

char* one = new char;

delete [] one; // Wrong

char* many = new char [30];

delete many; // Wrong!

6

Se a fuga ainda for permitida, normalmente procuro-a com o deleaker. http://deleaker.com). Obrigado!
 203
Author: John Smith, 2012-09-16 15:13:45
Pode usar algumas técnicas no seu código para detectar fugas de memória. A maneira mais comum e mais fácil de detectar é, definir uma macro say, DEBUG_NEW e usá-la, juntamente com macros predefinidos como __FILE__ e __LINE__ para localizar a fuga de memória no seu código. Estas macros predefinidas lhe dizem o arquivo e número de linha de vazamentos de memória.

A DEPURAÇÃO_ nova é apenas uma MACRO que é normalmente definida como:

#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW

Para que onde quer que use new, Ele também possa acompanhar o ficheiro e o número da linha que pode ser usado para localizar uma fuga de memória no seu programa.

E __FILE__, __LINE__ são macros predefinidos que avaliam para o nome do ficheiro e número da linha, respectivamente, onde os utiliza!

Leia o seguinte artigo, que explica a técnica de usar o DEBUG_NEW com outras macros interessantes, muito bem:

Um Detector De Fugas De Memória Multi-Plataforma


From Wikpedia,

A Depuração_new refere-se a uma técnica em C++ sobrecarregar e / ou redefinir o operador novo e operador apagar, a fim de interceptar a alocação de memória e chamadas de desallocação, e assim depurar a programa de uso de memória. Muitas vezes envolve definir uma macro chamada DEPURAR_ novo, e faz com que o novo se torne algo como novo (_ficheiro_, _linha _) para gravar a informação do ficheiro/linha em alocacao. Microsoft Visual C++ usa esta técnica em sua Microsoft Aulas Da Fundação. Há alguns formas de estender este método para evitar usar a redefinição da macro ainda capaz de mostrar o ficheiro / linha informação em algumas plataformas. La são muitas limitações inerentes a isso metodo. Aplica-se apenas a C++, e não é possível capturar fugas de memória por C funções como malloc. No entanto, pode ser muito simples de usar e também muito rápido, quando comparado com um pouco mais soluções completas de depurador de memória.

 25
Author: Nawaz, 2011-06-07 06:13:15
Existem algumas técnicas de programação bem conhecidas que o ajudarão a minimizar o risco de fugas de memória em primeira mão.
  • se tiver de fazer a sua própria alocação dinâmica de memória, escreva new e delete sempre em pares, e certifique-se que o código de alocação/deallocação é chamado em pares
  • evite a alocação dinâmica da memória se puder. Por exemplo, use vector<T> t sempre que possível em vez de T* t = new T[size]
  • usa "ponteiros inteligentes" como ponteiros inteligentes (http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/smart_ptr.htm)
  • o meu favorito: certifique-se de que entendeu o conceito de propriedade de um ponteiro, e certifique-se de que em todos os lugares onde você usa ponteiros, você sabe qual entidade de código é o proprietário {[[9]}
  • saiba que Construtores / operadores de atribuição são criados automaticamente pelo compilador C++, e o que isso significa se você tem uma classe que possui um ponteiro (ou o que isso significa se você tem uma classe que contém um ponteiro para um objeto que ele faz Não próprio).
 13
Author: Doc Brown, 2017-03-20 20:20:42
  1. telecarregamento Ferramentas de depuração para o Windows.
  2. Use o utilitário gflags para activar os vestígios da pilha no modo utilizador.
  3. utilizar UMDH para tirar várias fotos da memória do seu programa. Tire uma foto antes que a memória seja alocada, e tome uma segunda foto depois de um ponto em que você acredita que o seu programa vazou memória. Você pode querer adicionar pausas ou sugestões no seu programa para lhe dar uma chance de executar UMDH e tirar as fotos.
  4. corre. Mais uma vez, desta vez em seu modo que faz uma diferença entre os dois instantâneos. Ele irá então gerar um relatório contendo as pilhas de chamadas de supostas vazamentos de memória.
  5. reponha a sua configuração anterior {[[0]} quando terminar.

UMDH irá dar-lhe mais informações do que o CRT debug heap porque ele está assistindo alocações de memória em todo o seu processo; ele pode até dizer-lhe se os componentes de terceiros estão vazando.

 7
Author: Aaron Klotz, 2011-06-07 06:19:30
 6
Author: CantGetANick, 2012-09-27 08:31:27

Se usar o gcc, há gprof disponível.

Queria saber como o programador encontra uma fuga de memória.

Alguns usam ferramentas, alguns fazem o que você faz, também podem através da revisão do Código dos pares

Existe algum padrão ou procedimento que se deva seguir para garantir que não há fuga de memória no programa

Para mim: sempre que crio objectos dinamicamente alocados, coloco sempre o código de libertação depois, e depois preencho o código entre. Não faz mal. de certeza que não haverá excepções no código entre elas. Caso contrário, faço uso do try-finally (eu não Uso c++ frequentemente).

 5
Author: LeleDumbo, 2011-06-07 06:15:39
  1. No visual studio, há um detector construído para vazamento de memória chamado biblioteca C Runtime. Quando o seu programa sair após a função principal Voltar, O CRT irá verificar o monte de depuração da sua aplicação. se você tiver alguns blocos ainda alocados no monte de depuração, então você tem vazamento de memória..

  2. Este fórum discute algumas formas de evitar fugas de memória em C/C++..

 5
Author: Benny Tjia, 2011-06-07 06:25:11

Procure no seu código por ocorrências de {[[0]}, e certifique-se que todas ocorrem dentro de um construtor com uma eliminação correspondente num destruidor. Certifica-te que esta é a única operação possível naquele construtor. Uma maneira simples de fazer isso é embrulhar todos os ponteiros em std::auto_ptr, ou boost::scoped_ptr (dependendo se você precisa ou não de semântica de movimento). Para todos os códigos futuros apenas garantir que cada recurso é de propriedade de um objeto que limpa o recurso em seu destruidor. Se precisar de se mexer semântica então você pode atualizar para um compilador que suporta referências de Valor r (VS2010 does I believe) e criar construtores de movimento. Se você não quiser fazer isso, então você pode usar uma variedade de técnicas complicadas envolvendo uso consciente de troca, ou tentar o impulso.Mova a biblioteca.

 5
Author: Mankarse, 2011-12-19 02:06:16

Executar o" Valgrind " can:

1) Ajude a identificar vazamentos de memória - mostre quantas vazamentos de memória você tem, e aponte para as linhas no código onde a memória vazada foi alocada.

2) apontar as tentativas erradas de libertar a memória (por exemplo, chamada imprópria de "apagar")

Instruções de utilização de "Valgrind"

Chama o valgrindaqui .

1) Compile o seu código com-g flag

3) na sua casca run:

valgrind --leak-check=yes myprog arg1 arg2

Onde " myprog "é o seu programa compilado e" arg1"," arg2 " os argumentos do seu programa.

4) o resultado é uma lista de chamadas para malloc/new que não tiveram chamadas subsequentes para apagar gratuitamente.

Por exemplo:

==4230==    at 0x1B977DD0: malloc (vg_replace_malloc.c:136)

==4230==    by 0x804990F: main (example.c:6)

Diz-lhe em que linha o malloc (que não foi libertado) foi chamado.

Como apontado por outros, certifique-se de que para cada chamada "novo"/"malloc" você tem uma chamada subsequente "delete"/"livre".

 5
Author: Gal Nachmana, 2016-06-06 18:45:18

No Windows pode usar CRT debug heap .

Existe algum padrão ou procedimento que se deve seguir para garantir que não há nenhuma fuga de memória no programa.

Sim, não use gestão manual da memória (se alguma vez ligar para {[[0]} ou delete[] manualmente, então está a fazer mal). Use RAII e ponteiros inteligentes, limite as alocações de heap ao mínimo absoluto (A maior parte do tempo, variáveis automáticas serão suficientes).

 3
Author: Cat Plus Plus, 2011-06-07 06:15:04

Respondendo à segunda parte da tua pergunta,

Há algum padrão ou procedimento a seguir para garantir que não há fuga de memória no programa?
Sim, há. E esta é uma das principais diferenças entre C E C++.

Em C++, nunca deve ligar para {[[0]} ou delete no seu código de utilizador. RAII é uma técnica muito comum, que resolve praticamente o problema de gestão de recursos. Todos os recursos do seu programa (a de recursos é algo que tem de ser adquirida, e, posteriormente, lançado: identificadores de arquivos, sockets de rede, conexões de banco de dados, mas também simples alocações de memória e, em alguns casos, os pares de chamadas de API (BeginX()/EndX(), LockY(), UnlockY()), deve ser envolto em uma classe, onde:

  • O Construtor adquire O recurso (chamando {[[0]} se o recurso for uma atribuição memroy) {[[25]}
  • o destruidor liberta O recurso,
  • copiar e a atribuição é impedida (tornando privado O Construtor de cópias e os operadores de cessão), ou é implementada para funcionar corretamente (por exemplo, clonando o recurso subjacente)

Esta classe é então instanciada localmente, na pilha, ou como um membro da classe, e Não chamando new e armazenando um ponteiro.

Muitas vezes não precisas de definir estas aulas sozinho. Os recipientes da biblioteca padrão também se comportam desta forma, de modo que qualquer objeto armazenado em a std::vector é libertada quando o vector é destruído. Então, novamente, não armazene um ponteiro no recipiente (o que exigiria que você chamasse new e delete), mas sim o próprio objecto (O que lhe dá gestão de memória de graça). Da mesma forma, classes de ponteiros inteligentes podem ser usadas para embrulhar facilmente objetos que apenas têm que ser alocados com {[[0]}, e controlar suas vidas. Isso significa que quando o objeto sai do escopo, ele é automaticamente destruído, e seu recurso liberado e limpo. Se você fizer isso de forma consistente ao longo de seu código, você simplesmente não terá nenhuma perda de memória. Tudo o que conseguiu vazar Está ligado a um destruidor que é garantido ser chamado quando o controle deixa o escopo em que o objeto foi declarado.
 3
Author: jalf, 2011-06-07 06:32:30

O detector de fugas visuais (VLD) é um sistema de detecção de fugas de memória livre, robusto e de código aberto para C++Visual.

Quando executar o seu programa sob o depurador Visual Studio, O detector de fugas visuais emitirá um relatório de fugas de memória no final da sua sessão de depuração. O relatório de fugas inclui a pilha de chamadas completa que mostra como os blocos de memória vazados foram alocados. Duplo-click em uma linha na pilha de chamadas para saltar para esse arquivo e linha no editor janela.

Se só tiver estoiros, poderá usar o comando Windbg !heap -l, que irá detectar os blocos de heap vazados. É melhor abrir a opção gflags:" criar a base de dados de rastreamento de modo de usuário", então você vai ver a pilha de chamadas de alocação de memória.

 3
Author: fresky, 2014-09-15 10:15:10

MTuner é uma ferramenta de análise e detecção de fugas que suporta Compiladores MSVC, GCC e Clang. As características incluem:

  • cronograma histórico de Utilização da memória e blocos de memória ao vivo
  • filtragem poderosa da operação de memória baseada no heap, marca de memória, intervalo de tempo, etc.
  • SDK para instrumentação manual com código-fonte completo
  • suporte contínuo de integração através da utilização da linha de comandos
  • árvore de pilha de chamadas e navegação por mapa das árvores
  • Muito mais.

Os utilizadores podem analisar qualquer plataforma de alvos de software com GCC ou Clang cross. compilador. A MTuner vem com suporte para Windows, PlayStation 4 e PlayStation 3.

 3
Author: mtosic, 2016-10-25 01:51:02

AddressSanitizer (ASan) é um detector de erros de memória rápido. Ele encontra bugs de overflow do use-after-free e {heap,stack,global}-buffer em programas C/C++. Encontra:

  • Utilizar depois de livre (dereferência do ponteiro)
  • Heap buffer overflow
  • estouro do buffer de pilha
  • Overflow global buffer
  • Utilizar após o retorno
  • erros da ordem de inicialização

Esta ferramenta é muito rápida. A desaceleração média do programa instrumentado é ~2x.

 1
Author: Beginner, 2015-02-08 19:13:21

Pode usar a ferramenta Valgrind para detectar fugas de memória.

Também, para encontrar a fuga numa função em particular, use o exit( 0) no fim da função e depois execute-a com Valgrind

`$` valgrind ./your_CPP_program 
 1
Author: Divyanshu, 2018-07-21 11:36:59
Para além das ferramentas e métodos fornecidos nos outros anwers, podem ser utilizadas ferramentas estáticas de análise de códigos para detectar fugas de memória (e outras questões também). Uma ferramenta robusta gratuita é Cppcheck. Mas há muitas outras ferramentas disponíveis. O Wikipedia tem uma lista de ferramentas estáticas de análise de códigos.
 0
Author: orbitcowboy, 2017-07-05 19:10:59
Isto pode ajudar alguém que só quer usar o Visual Studio para detectar fugas. "Ferramentas de diagnóstico" navios com VS 2015 e acima versões são muito melhorados agora. Também tentou ferramenta chamada "Deleaker", mas Visual studio ferramenta é igualmente bom. Ver o vídeo seguinte ajudou-me a começar.

Https://www.youtube.com/watch?v=HUZW8m_3XvE

 0
Author: Patel, 2017-07-14 22:16:19

Nunca deve ser utilizado em código de Aplicação "novo" ou "apagar". Em vez disso, crie um novo tipo que use o idioma gerente / trabalhador, no qual a classe gerente aloca e liberta a memória e encaminha todas as outras operações para o objeto trabalhador.

Infelizmente isto é mais trabalho do que deveria ser porque o C++ não tem sobrecarga de "operador".". É ainda mais trabalho na presença de polimorfismo.

Mas vale a pena o esforço, porque nunca terás de o fazer. preocupa-te com fugas de memória, o que significa que nem tens de as Procurar.
 0
Author: s. heller, 2018-02-20 14:35:23