Pular para o conteúdo

Ponteiros e memória crua

Endereço com tipo, aritmética de ponteiro, memória alocada à mão e o nulo que se reconhece antes de derrubar o processo.

Um ponteiro aqui é um endereço com tipo. O tipo não é decoração: é ele que diz quanto deslocar(1) anda e como ler() interpreta os bytes.

dataforge
adopt Arcane.C as C

bloco := C.alocar(4 * C.tamanho_de("i32"))
p := C.ponteiro(bloco, "i32")

cycle i from 0 to 3:
    p.deslocar(i).escrever(i * 10)

assert p.ler() is 0
assert p.deslocar(2).ler() is 20
assert [p.deslocar(i).ler() cycle i in range(0, 4)] is [0, 10, 20, 30]

C.liberar(bloco)
SímboloO que faz
C.ponteiro(alvo, tipo)ponteiro a partir de endereço, bloco ou struct
p.ler() · p.escrever(v)lê e escreve no tipo declarado
p.deslocar(n)anda n itens — a aritmética de ponteiro
p.deslocar_bytes(n)anda n bytes, quando o passo não é o tipo
p.como(tipo)o mesmo endereço lido como outro tipo — o cast
p.bytes(n) · p.texto()lê memória crua, ou uma string terminada em zero
p.endereco() · p.e_nulo()o número, e a pergunta que evita o desastre

O nulo é conferido#

Ler um endereço nulo derruba o processo, e a pilha não fala do DataForge. Essa é a única conferência que vale o custo — o resto da segurança de memória, em FFI, é de quem chama.

dataforge
adopt Arcane.C as C

nulo := C.nulo()
assert nulo.e_nulo() and nulo.endereco() is 0

monitor:
    nulo.ler()
    assert no
handle RuntimeError as e:
    assert "nulo" in e.message

Memória alocada à mão#

dataforge
adopt Arcane.C as C
adopt Arcane.Bytes as B

dados := C.de_bytes("dataforge")
assert B.para_texto(C.para_bytes(dados, 9)) is "dataforge"
assert dados.tamanho() is 10          // o zero do fim conta

outro := C.alocar(16)
C.copiar(outro, dados, 9)
assert B.para_texto(C.para_bytes(outro, 9)) is "dataforge"

C.liberar(dados)
C.liberar(outro)
dataforge
adopt Arcane.C as C
adopt Arcane.Posse as P

// o bloco sai junto com o escopo, mesmo se o corpo falhar
valor := P.com(P.dono(C.alocar(32), lambda b => C.liberar(b)),
               lambda bloco => bloco.tamanho())

assert valor is 32