Pular para o conteúdo

4. Contenção, revisão e testes

Revise código unsafe por invariante. Em cada acesso bruto, identifique quem estabeleceu validade, tamanho, alinhamento, inicialização, aliasing, mutabilidade e tempo de vida. Em cada alocação, identifique o único responsável pela limpeza e o que ocorre em falhas anteriores. Em cada chamada nativa, registre a fonte da ABI e os alvos compatíveis.

Teste o wrapper seguro com tamanhos zero, um, limite e inválido; entradas nulas e vazias; repetição; falha de alocação injetada quando disponível; e limpeza após progresso parcial. Sanitizers são evidência, não prova.

Mantenha o módulo unsafe privado, exponha operações tipadas, documente a invariante junto da fronteira e exija revisão focada. Se um recurso seguro puder expressar a operação depois, remova o caminho unsafe.

Exemplo testado

Mantenha o acesso bruto em dois blocos curtos e verifique o valor seguro antes e depois da fronteira.

Arquivo: curriculum/main-evidence/single/unsafe_pointers.fl

curriculum/main-evidence/single/unsafe_pointers.fl
// Build: build/flecha build examples/unsafe_pointers.fl -o build/unsafe_pointers
// Prints 42 and exits with 42. All pointers below refer to live local storage.
unsafe void write(constptr i32 destination, i32 value) {
// The pointer binding is fixed; its target remains writable.
*destination = value;
}
unsafe i32 read(*const i32 source) {
// The target is read-only, including inside this unsafe function.
return *source;
}
*i32 pass_pointer(*i32 pointer) {
// Copying an address does not access its target and needs no unsafe block.
return pointer;
}
i32 main() {
i32 value = 0;
*i32 pointer = none;
if pointer != null { return 1; }
unsafe {
pointer = &raw value;
write(pointer, 40);
constptr i32 fixed = pointer;
*fixed = *fixed + 2;
// Read-only access may be added, but never removed implicitly.
*const i32 readOnly = fixed;
if read(readOnly) != 42 { return 2; }
// Nested pointers preserve each layer's qualifiers.
**i32 slot = &raw pointer;
if **slot != 42 { return 3; }
}
pointer = pass_pointer(pointer);
unsafe {
// value still lives here. The unsafe block did not free anything.
if *pointer != 42 { return 4; }
}
stdoutln(value);
return value;
}

O bloco acima é o arquivo completo executado pelos comandos abaixo.

Os dois acessos brutos são curtos e cercados por valores seguros verificáveis antes e depois da fronteira. Ampliar a região bruta faria a mesma invariante valer para mais código sem adicionar capacidade.

Comandos

Comandos
flecha check curriculum/main-evidence/single/unsafe_pointers.fl
flecha build curriculum/main-evidence/single/unsafe_pointers.fl -o build/unsafe_pointers
build/unsafe_pointers

Saída esperada

Saída esperada
42
status de saída: 42

Referência relacionada: /examples/unsafe_pointers/.

Use exemplos para aplicativos completos e a documentação de referência para contratos precisos. Nenhum deles cria um Próximo acidental nesta sequência.