[C++] Gerenciamento de memória C/C++ - novo, excluir


ヾ(๑╹◡╹)ノ" As pessoas sempre têm que pagar pela preguiça do passadoヾ(๑╹◡╹)ノ"
insira a descrição da imagem aqui


1. Distribuição de memória C/C++

Exibição de código:

#include <iostream>
int a = 1;//a在静态区(数据段)
static int b = 1;//b在静态区(数据段)
int main()
{
    
    
	static int c = 1;//c在静态区(数据段)
	int d = 1;//d在栈区
	int num[10] = {
    
     1, 2, 3 };//num在栈区
	const char c[] = "abcd";//c和*c在栈区;常量字符串的内容拷贝一份,赋值给数组c,所以这个字符串不是在常量区
	const char* p = "abcd";//p在栈区,在栈区创建一个变量p,来储存常量字符串的地址
	//*p在常量区:*p是p所指向的内容,常量字符串,
	int* p1 = (int*)malloc(sizeof(int) * 4);//p1在栈区,*p1是指针指向的地址,这个地址在堆区
	int* p2 = (int*)calloc(4, sizeof(int));
	int* p3 = (int*)realloc(p2, sizeof(int) * 4);
	free(p1);
	free(p2);
	return 0;
}

Área da pilha: variável local
sizeof (nome do array): o tamanho de todo o array
sizeof (string): note '\0'

  1. A pilha também é chamada de pilha – variáveis ​​locais/parâmetros de função/valores de retorno não estáticos, etc., a pilha cresce para baixo.
  2. Segmentos mapeados em memória são mapeamentos de E/S eficientes para carregar um banco de memória dinâmica compartilhada. Os usuários podem usar a interface do sistema para criar memória compartilhada para comunicação entre processos. (aprender)
  3. O heap é usado para alocação dinâmica de memória quando o programa está em execução e o heap pode crescer para cima.
  4. Segmento de dados - armazena dados globais e estáticos.
  5. Seção de código (área constante) - código executável/constantes somente leitura.

2. Gerenciamento dinâmico de memória em C/C++

2.1 Gerenciamento dinâmico de memória em linguagem C

malloc/calloc/realloc/livre
Questões de entrevista: A diferença entre malloc/calloc/realloc?

2.2 Método de gerenciamento de memória C++

C++ implementa gerenciamento dinâmico de memória por meio de operadores novos e de exclusão. [Novo espaço aberto dinamicamente não precisa verificar se foi aberto com sucesso]

  • Para tipos integrados, não há diferença
  • A diferença está no tipo personalizado, tipo personalizado C++: [novo] criar espaço + chamar inicialização do construtor [delete] chamar o destruidor para limpar recursos + liberar espaço [falha de criação: lançar exceção]; Linguagem C: [malloc] apenas criar espaço [gratuito] apenas libera espaço [falha ao criar: retornar ponteiro nulo]
int main()
{
    
    
	int* p1 = new int;//new 1个对象
	int* p2 = new int[10];//new 10个对象
	int* p3 = new int(10);//new 1个对象,值初始化为10
	int* p4 = new int[6]{
    
     1, 2, 3, 4 };//new 6个对象,值初始化分别为1、2、3、4、0、0(C++11才支持)
	delete p1;//new出来的
	delete[] p2;//new[]出来的
	delete p3;//new出来的
	delete[] p4;//new[]出来的
	//注意要匹配,如果不匹配,不一定会报错。但是还是要匹配
	return 0;
}

Perceber: (1) Para solicitar e liberar o espaço de um único elemento, use os operadores new e delete para solicitar e liberar espaço contínuo, use new[] e delete[], nota: combine e use.
(2) Ao solicitar um tipo de espaço personalizado, new chamará o construtor, delete chamará o destruidor, mas malloc e free will não.

Três, funções de operador novo e exclusão de operador

3.1 funções de operador novo e exclusão de operador

  • new e delete são operadores para os usuários aplicarem e liberarem memória dinâmica . O operador new e o operador delete são funções globais fornecidas pelo sistema . new chama o operador nova função global na camada inferior para solicitar espaço, e delete usa o operador delete global função na camada inferior para liberar espaço.
  • O operador new realmente se aplica ao espaço por meio do malloc. Se o malloc solicitar espaço com sucesso, ele retornará diretamente. Caso contrário, ele executará as contramedidas fornecidas pelo usuário por espaço insuficiente. Se o usuário fornecer essa medida, ela continuará a ser aplicada, caso contrário isso lançará uma exceção. o operador delete finalmente libera espaço gratuitamente.

3.2 Sobrecarga específica de classe do operador new e operador delete (entenda)

  • Solicitar espaço no heap é mais rápido do que solicitar espaço no conjunto de memória.
  • Sobrecarregue a função exclusiva do operador novo/de exclusão do operador, implemente a função e solicite espaço do conjunto de memória. É equivalente a solicitar espaço no pool de memória com mais rapidez. Use o pool de memória para aplicar e liberar memória para melhorar a eficiência.

Em quarto lugar, o princípio de realização de novo e de exclusão

tipo embutido

Se você solicitar um tipo de espaço integrado, new e malloc, delete e free são basicamente semelhantes, a diferença é: new/delete se aplica e libera o espaço de um único elemento, new[] e delete[] se aplicam a espaço contínuo. Além disso, new lançará uma exceção quando não solicitar espaço e malloc retornará NULL.

tipo personalizado

  • O princípio do novo
  1. Chame a nova função do operador para solicitar espaço
  2. Execute o construtor no espaço solicitado para concluir a construção do objeto
  • O princípio da exclusão
  1. Execute o destruidor no espaço para completar a limpeza dos recursos no objeto
  2. Chame a função delete do operador para liberar o espaço do objeto
  • O princípio do novo T[N]
  1. Chame a função do operador new[] e, na verdade, chame a função do operador new no operador new[] para completar a aplicação de N espaços de objetos
  2. Execute o construtor N vezes no espaço solicitado
  • O princípio da exclusão[]
  1. Execute N vezes de destruidores no espaço de objetos liberado para completar a limpeza de recursos em N objetos
  2. Chame o operador delete[] para liberar espaço, na verdade, chame o operador delete no operador delete[] para liberar espaço

Cinco, posicionando nova expressão (posicionamento-novo) (compreender)

Posicionar a nova expressão é chamar o construtor para inicializar um objeto no espaço de memória original alocado .
Use o formato:
novo tipo (place_address) ou novo tipo (place_address) (lista de inicializadores)
place_address deve ser um ponteiro , lista de inicializadores é a lista de inicialização do tipo
cenas a serem usadas:
O posicionamento de novas expressões geralmente é usado em conjunto com conjuntos de memória na prática . Como a memória alocada pelo pool de memória não é inicializada, se for um objeto de tipo customizado, ele precisará usar a expressão de definição new para chamar explicitamente o construtor para inicialização.
new(obj)Data(3) é equivalente a: Data* obj = nova Data(3)

6. Perguntas da entrevista

A diferença entre malloc/free e new/delete[Uso 1-4 e Diferença 5-6]
O ponto comum entre malloc/free e new/delete é que ambos solicitam espaço do heap e precisam ser liberados manualmente pelo usuário. As diferenças são:

  1. malloc e free são funções, new e delete são operadores
  2. O espaço solicitado pelo malloc não será inicializado, mas new poderá ser inicializado
  3. Quando malloc se aplica ao espaço, você precisa calcular manualmente o tamanho do espaço e passá-lo adiante. New só precisa seguir com o tipo de espaço. Se houver vários objetos, especifique o número de objetos em []
  4. O valor de retorno de malloc é void*, que deve ser forçado quando usado, e new não precisa dele, porque new é seguido pelo tipo de espaço
  5. Quando malloc não solicita espaço, ele retorna NULL, portanto deve ser considerado vazio ao usá-lo, new não precisa dele, mas new precisa capturar exceções
  6. Ao solicitar um tipo de objeto personalizado, malloc/free apenas abrirá espaço e não chamará o construtor e o destruidor, enquanto new chamará o construtor para completar a inicialização do objeto após solicitar espaço, e delete chamará o destruidor antes de liberar o espaço Conclua a limpeza de recursos no espaço

vazamento de memória

  • O que é um vazamento de memória, os danos dos vazamentos de memória
  1. O que é um vazamento de memória: Um vazamento de memória refere-se a uma situação em que um programa não consegue liberar memória que não está mais em uso devido a negligência ou erro. Um vazamento de memória não se refere ao desaparecimento físico da memória, mas sim à perda de controle sobre um determinado segmento de memória devido a um erro de design após o aplicativo alocar um determinado segmento de memória, resultando em desperdício de memória .
  2. Perigos de vazamentos de memória: Vazamentos de memória ocorrem em programas de longa execução, que têm um grande impacto, como sistemas operacionais, serviços em segundo plano, etc. Vazamentos de memória levarão a respostas cada vez mais lentas e, eventualmente, congelarão.
    Um vazamento de memória é um ponteiro perdido
  • Classificação de vazamentos de memória (compreensão)
  1. Vazamento de memória heap (vazamento de heap): A memória heap refere-se a um pedaço de memória alocado do heap por meio de malloc / calloc / realloc / new, etc. durante a execução do programa conforme necessário. Após o uso, ele deve ser excluído chamando o correspondente free ou excluir
    . Supondo que o erro de design do programa faça com que esta parte da memória não seja liberada, então esta parte do espaço não será mais usada no futuro e ocorrerá Heap Leak.
  2. Vazamento de recursos do sistema : Refere-se aos recursos alocados pelo sistema utilizados pelo programa, como soquetes, descritores de arquivos, pipes, etc., que não são liberados por meio das funções correspondentes, resultando em desperdício de recursos do sistema, o que pode levar seriamente ao desempenho reduzido do sistema e à execução instável do sistema.
  • Como evitar vazamentos de memória
  1. Boas especificações de design no estágio inicial do projeto, desenvolva bons padrões de codificação e lembre-se de liberar o espaço de memória correspondente. ps: Este estado ideal. Mas se você encontrar uma exceção, mesmo prestando atenção à liberação, ainda poderá haver problemas. Ele precisa ser gerenciado pelo próximo ponteiro inteligente para ser garantido.
  2. Use ideias RAII ou ponteiros inteligentes para gerenciar recursos.
  3. Algumas especificações internas da empresa usam bibliotecas privadas de gerenciamento de memória implementadas internamente. Esta biblioteca vem com opções para detecção de vazamento de memória.
  4. Algo deu errado ao usar uma ferramenta de vazamento de memória para detectar. ps: No entanto, muitas ferramentas não são confiáveis ​​o suficiente ou as taxas são caras.
    Vazamentos de memória são muito comuns e existem duas soluções: 1, tipo pré-prevenção. Como ponteiros inteligentes, etc. 2. Tipo de verificação de erro pós-evento. Como ferramentas de detecção de vazamentos.

Conhecimento complementar:
Problema de otimização do compilador : (construtor) [a otimização depende apenas do compilador]

  • Objeto anônimo : o ciclo de vida é apenas esta linha, [classe: o construtor e o destruidor serão chamados nesta linha]tipo()[Exemplo: Data() ]
  • Cenário de uso : quando apenas uma função da classe precisa ser chamadaclasse.função(por exemplo: Data().num(10) )
  1. Em uma expressão: construção consecutiva + construção de cópia será otimizada
    f(Date()); //Date(), executa a construção e, em seguida, imediatamente () copia a construção, o compilador otimiza. Basta otimizar diretamente para um construtor. dentro da expressão de uma linha
  2. Em uma expressão: construções de cópias consecutivas também serão otimizadas
    Data ret = f(x); f(x) retorna por valor, uma variável temporária, uma construção de cópia, atribuindo um valor a
    ret para uma construção de cópia. Então otimizado.

Resumir

Falarei sobre o que foi dito acima hoje: este artigo apresenta a distribuição de memória C/C++, métodos de gerenciamento dinâmico de memória, funções de operador new e operador delete e os princípios de implementação de new e delete em detalhes. Espero ajudar amigos!

Acho que você gosta

Origin blog.csdn.net/m0_57388581/article/details/132500250
Recomendado
Clasificación