Alinhamento e divisão
Torne os blocos utilizáveis e organizados.
Alinhamento e divisão é uma aula grátis de C Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C Academy inclui 4 aulas no total.
Por que o Alinhamento é Importante
Todo tipo tem um requisito de alinhamento: seu endereço deve ser múltiplo de alguma potência de dois. Um double normalmente precisa de alinhamento de 8 bytes.
Como malloc não sabe o que será armazenado, ele deve retornar ponteiros alinhados para o tipo mais exigente, normalmente 16 bytes em sistemas de 64 bits.
#include <stdalign.h>
/* the strictest fundamental alignment */
size_t strict = alignof(max_align_t); /* often 16 */O Truque align_up
Arredondar um tamanho para cima até o próximo múltiplo de um alinhamento que seja potência de dois é um truque clássico de bits: some a - 1 e depois mascare os bits inferiores.
Isso funciona somente quando a é uma potência de dois, como ocorre com todos os alinhamentos reais.
static size_t align_up(size_t n, size_t a) {
return (n + a - 1) & ~(a - 1);
}
/* align_up(13, 8) == 16, align_up(16, 8) == 16 */Comprovando que a Matemática Funciona
Vamos verificar align_up com um programa executável. Ele arredonda vários tamanhos para limites de 8 e 16 bytes e imprime os resultados.
#include <stdio.h>
#include <stddef.h>
static size_t align_up(size_t n, size_t a) {
return (n + a - 1) & ~(a - 1);
}
int main(void) {
printf("%zu\n", align_up(13, 8)); /* 16 */
printf("%zu\n", align_up(16, 8)); /* 16 */
printf("%zu\n", align_up(1, 16)); /* 16 */
printf("%zu\n", align_up(33, 16)); /* 48 */
return 0;
}Alinhando os Tamanhos Solicitados
Dentro do alocador, o primeiro passo de toda solicitação é arredondar o tamanho solicitado para o alinhamento. Isso garante que o próximo bloco também comece alinhado.
Os bytes de preenchimento são fragmentação interna, o preço do alinhamento universal.
#define ALIGN 16
void *my_alloc(size_t size) {
size = align_up(size, ALIGN);
/* now find a block of this aligned size */
/* ... */
return NULL;
}O Problema da Reutilização do Bloco Inteiro
Na lição anterior, retornamos um bloco livre inteiro mesmo para solicitações pequenas. Entregar um bloco livre de 4000 bytes para uma solicitação de 16 bytes desperdiça o restante.
A divisão separa o bloco na parte que usamos e em um restante que continua livre.
Dividindo um Bloco
Se um bloco escolhido for muito maior do que o necessário, colocamos um novo cabeçalho no fim da região solicitada. O restante se torna um bloco livre menor na lista.
Só dividimos quando o restante é grande o suficiente para conter um cabeçalho e algum conteúdo; caso contrário, o fragmento não tem utilidade.
void split(block_t *b, size_t size) {
size_t rem = b->size - size;
if (rem < sizeof(block_t) + ALIGN) return; /* too small */
block_t *nb = (block_t *)((char *)(b + 1) + size);
nb->size = rem - sizeof(block_t);
nb->free = 1;
nb->next = b->next;
b->size = size;
b->next = nb;
}Alocar, Alinhar, Dividir
Agora, o fluxo completo de alocação alinha o tamanho, encontra um encaixe, separa qualquer restante grande e marca o bloco como usado.
Isso mantém os blocos dimensionados de forma precisa e deixa espaço livre utilizável.
void *my_alloc(size_t size) {
size = align_up(size, ALIGN);
block_t *b = first_fit(size);
if (!b) return NULL;
split(b, size);
b->free = 0;
return (void *)(b + 1);
}Mantendo o Próprio Pool Alinhado
Para garantir a correção, o endereço inicial do pool e o tamanho do cabeçalho também devem respeitar o alinhamento, para que todo conteúdo caia em um limite adequado.
Usar alignas no buffer estático garante que todo o esquema comece alinhado.
#include <stdalign.h>
alignas(16) static unsigned char pool[4096];
/* pool now begins on a 16-byte boundary */Uma Alocação Alinhada Executável
Este programa aloca a partir de um pool alinhado e imprime o endereço retornado módulo 16, mostrando que o resultado é sempre zero, ou seja, que está devidamente alinhado.
#include <stdio.h>
#include <stddef.h>
#include <stdalign.h>
static size_t align_up(size_t n, size_t a){ return (n+a-1)&~(a-1); }
alignas(16) static unsigned char pool[1024];
static size_t off = 0;
void *alloc16(size_t s){ off=align_up(off,16); if(off+s>sizeof(pool)) return NULL; void*p=&pool[off]; off+=s; return p; }
int main(void){
void *a = alloc16(1);
void *b = alloc16(20);
printf("a %% 16 = %lu\n", (unsigned long)((size_t)a % 16));
printf("b %% 16 = %lu\n", (unsigned long)((size_t)b % 16));
return 0;
}Divisão versus Coalescência
Divisão e coalescência são opostos que se equilibram. A alocação divide os blocos grandes; a liberação combina novamente os blocos pequenos.
Juntas, elas permitem que o mesmo pool atenda a uma combinação variável de tamanhos de solicitação sem vazar espaço nem se fragmentar permanentemente.
Do Exemplo ao Alocador Real
Agora você tem os quatro pilares: uma fonte de memória, cabeçalhos alinhados, reutilização por lista livre com coalescência e divisão. Os alocadores reais adicionam compartimentos por classe de tamanho, caches de threads e integração com o OS para obter velocidade e escala.
Mas as ideias centrais desenvolvidas aqui impulsionam toda implementação de malloc.
Verificação Rápida
Considere por que os blocos são divididos durante a alocação.
Recapitulação
O alinhamento arredonda os tamanhos para cima com o truque de bits (n + a - 1) & ~(a - 1), para que todo conteúdo seja adequado a qualquer tipo. A divisão transforma blocos livres grandes demais em uma parte usada e um restante livre, enquanto a coalescência desfaz isso durante a liberação.
Juntos, esses quatro pilares formam um alocador de memória completo e correto.
Perguntas Frequentes
A aula “Alinhamento e divisão” é grátis?
Sim — o texto completo de “Alinhamento e divisão” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C Academy, atualize para CoddyKit PRO. O curso de C Academy inclui 4 aulas no total.
O que vou aprender em “Alinhamento e divisão”?
Torne os blocos utilizáveis e organizados. Você pratica C Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar C Academy?
Nenhuma experiência prévia é necessária. C Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Alinhamento e divisão”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de C Academy?
Sim. Cada aula de C Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Como funciona malloc
- Um alocador bump simples
- Listas livres e reutilização
- Alinhamento e divisão