/** * ============================================================================ * PHM Tech & PHM Open Source · Prof. Paulo Henrique Maciel * Módulo 09: Alocação Dinâmica de Memória na Heap & Prevenção de Memory Leaks * ============================================================================ * * OBJETIVO PEDAGÓGICO: * Compreender a gestão manual da memória Heap em tempo de execução utilizando * malloc(), calloc(), realloc() e free(). Aprender a verificar ponteiros nulos * (NULL check), redimensionar buffers dinamicamente e evitar vazamentos de memória * (Memory Leaks) e ponteiros soltos (Dangling Pointers). * * CONCEITOS-CHAVE: * 1. Stack vs Heap (Alocação Estática/Automática vs Alocação Dinâmica). * 2. malloc(tamanho_bytes): Aloca bloco contíguo na Heap com lixo de memória. * 3. calloc(num_elementos, tamanho_bytes): Aloca e zera (0x00) todos os bytes. * 4. realloc(ponteiro, novo_tamanho): Redimensiona bloco sem perder dados. * 5. free(ponteiro): Devolve a memória ao Sistema Operacional. * 6. Prevenção de Memory Leak e anulação de ponteiros (ponteiro = NULL). * * COMO COMPILAR E EXECUTAR: * Windows (GCC/MinGW): gcc 09_alocacao_dinamica_heap.c -o m09.exe && m09.exe * Linux / macOS: gcc 09_alocacao_dinamica_heap.c -o m09 && ./m09 * ============================================================================ */ #include #include // Necessário para malloc, calloc, realloc e free #include void exibir_vetor(const int *vetor, int tamanho, const char *descricao) { printf("\n--- %s (Tamanho: %d elementos) ---\n", descricao, tamanho); for (int i = 0; i < tamanho; i++) { printf(" [Índice %d] Endereço: %p -> Valor: %d\n", i, (void*)&vetor[i], vetor[i]); } } int main(void) { printf("===============================================================\n"); printf(" AULA 09: ALOCAÇÃO DINÂMICA DE MEMÓRIA NA HEAP (C17)\n"); printf(" Prof. Paulo Henrique Maciel · PHM Tech Open Source\n"); printf("===============================================================\n\n"); int tamanho_inicial = 5; // ------------------------------------------------------------------------ // PARTE 1: ALOCAÇÃO COM malloc() (Memory Allocation) // ------------------------------------------------------------------------ printf("[1] Alocando vetor de inteiros dinamicamente com malloc()...\n"); int *vetor = (int *) malloc(tamanho_inicial * sizeof(int)); // Validação Defensiva: Verificar se o Sistema Operacional concedeu a memória if (vetor == NULL) { fprintf(stderr, "ERRO CRÍTICO: Falha na alocação de memória (RAM insuficiente)!\n"); return EXIT_FAILURE; } printf(" -> Memória concedida com sucesso! Bloco base: %p\n", (void*)vetor); // Preenchendo os dados for (int i = 0; i < tamanho_inicial; i++) { vetor[i] = (i + 1) * 10; // 10, 20, 30, 40, 50 } exibir_vetor(vetor, tamanho_inicial, "Vetor Inicial alocado com malloc()"); // ------------------------------------------------------------------------ // PARTE 2: REDIMENSIONAMENTO COM realloc() (Re-Allocation) // ------------------------------------------------------------------------ int novo_tamanho = 8; printf("\n[2] Redimensionando vetor para %d elementos com realloc()...\n", novo_tamanho); // Boa prática: usar ponteiro temporário para evitar perda do ponteiro original em caso de falha int *temp = (int *) realloc(vetor, novo_tamanho * sizeof(int)); if (temp == NULL) { fprintf(stderr, "ERRO: Não foi possível expandir a memória.\n"); free(vetor); // Libera o bloco anterior para não vazar memória return EXIT_FAILURE; } vetor = temp; // Inicializando as novas posições expandidas for (int i = tamanho_inicial; i < novo_tamanho; i++) { vetor[i] = (i + 1) * 100; // 600, 700, 800 } exibir_vetor(vetor, novo_tamanho, "Vetor Expandido com realloc()"); // ------------------------------------------------------------------------ // PARTE 3: ALOCAÇÃO ZERADA COM calloc() (Contiguous Allocation) // ------------------------------------------------------------------------ int tamanho_calloc = 4; printf("\n[3] Alocando vetor limpo com calloc() (todos bytes zerados 0x00)...\n"); int *vetor_zerado = (int *) calloc(tamanho_calloc, sizeof(int)); if (vetor_zerado == NULL) { free(vetor); return EXIT_FAILURE; } exibir_vetor(vetor_zerado, tamanho_calloc, "Vetor Zerado (calloc)"); // ------------------------------------------------------------------------ // PARTE 4: LIBERAÇÃO CORRETA COM free() & ANULAÇÃO DE PONTEIROS // ------------------------------------------------------------------------ printf("\n[4] Liberando blocos de memória Heap e anulando ponteiros...\n"); // Libera a memória alocada free(vetor); vetor = NULL; // Previne 'Dangling Pointer' (Ponteiro Solto) free(vetor_zerado); vetor_zerado = NULL; printf(" -> Memória devolvida com sucesso ao SO. Nenhum Memory Leak restante!\n\n"); printf("===============================================================\n"); printf(" PROGRAMA CONCLUÍDO COM SUCESSO!\n"); printf("===============================================================\n"); return EXIT_SUCCESS; }