💻 Exemplos de Código: Cap 15 - Alocação Dinâmica e Valgrind
Código executável completo demonstrando ciclo de vida seguro no Heap, expansão dinâmica com realloc e limpeza total para auditoria com Valgrind.
📄 Exemplo 1: Vetor Dinâmico Redimensionável (vetor_dinamico.c)
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct {
int *dados;
size_t tamanho;
size_t capacidade;
} VetorDinamico;
bool inicializarVetor(VetorDinamico *v, size_t capacidadeInicial) {
v->dados = (int*)malloc(capacidadeInicial * sizeof(int));
if (v->dados == NULL) return false;
v->tamanho = 0;
v->capacidade = capacidadeInicial;
return true;
}
bool adicionarElemento(VetorDinamico *v, int elemento) {
if (v->tamanho == v->capacidade) {
size_t novaCapacidade = v->capacidade * 2;
printf(">> [HEAP]: Expandindo capacidade de %zu para %zu elementos...\n",
v->capacidade, novaCapacidade);
// Padrão seguro de realocação com ponteiro temporário
void *temp = realloc(v->dados, novaCapacidade * sizeof(int));
if (temp == NULL) {
fprintf(stderr, "[ERRO]: Falha de memoria ao expandir Heap!\n");
return false;
}
v->dados = (int*)temp;
v->capacidade = novaCapacidade;
}
v->dados[v->tamanho++] = elemento;
return true;
}
void liberarVetor(VetorDinamico *v) {
if (v->dados != NULL) {
free(v->dados);
v->dados = NULL; // Neutralização anti-dangling
}
v->tamanho = 0;
v->capacidade = 0;
}
int main(void) {
VetorDinamico v;
printf("====================================================\n");
printf(" 💾 VETOR DINAMICO NO HEAP COM EXPANSÃO AUTOMATICA\n");
printf("====================================================\n");
if (!inicializarVetor(&v, 2)) {
fprintf(stderr, "Falha na alocacao inicial!\n");
return EXIT_FAILURE;
}
for (int i = 10; i <= 60; i += 10) {
adicionarElemento(&v, i);
}
printf("\nElementos no Vetor Dinamico (%zu itens):\n[ ", v.tamanho);
for (size_t i = 0; i < v.tamanho; i++) {
printf("%d ", v.dados[i]);
}
printf("]\n");
// Limpeza total de memória (Valgrind Clean)
liberarVetor(&v);
printf(">> Memoria desalocada com sucesso. Valgrind Clean! ✅\n");
printf("====================================================\n");
return EXIT_SUCCESS;
}
📄 Exemplo 2: Alocação de Matriz Dinâmica 2D Contígua (matriz_dinamica.c)
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t linhas = 3;
size_t colunas = 4;
// Alocação contígua em um único bloco de Heap (Alta Localidade de Cache)
int *matriz = (int*)calloc(linhas * colunas, sizeof(int));
if (matriz == NULL) {
fprintf(stderr, "Falha ao alocar matriz!\n");
return EXIT_FAILURE;
}
// Preenchimento utilizando a fórmula de linearização: (i * colunas + j)
for (size_t i = 0; i < linhas; i++) {
for (size_t j = 0; j < colunas; j++) {
matriz[i * colunas + j] = (int)((i + 1) * 10 + (j + 1));
}
}
printf("====================================================\n");
printf(" 📐 MATRIZ DINAMICA 2D CONTIGUA NO HEAP (3x4)\n");
printf("====================================================\n");
for (size_t i = 0; i < linhas; i++) {
printf("[ ");
for (size_t j = 0; j < colunas; j++) {
printf("%3d ", matriz[i * colunas + j]);
}
printf("]\n");
}
free(matriz);
matriz = NULL;
printf("====================================================\n");
return EXIT_SUCCESS;
}