---
title: "integer overflow at runtime — Como Resolver em Zig"
url: "https://ziglang.com.br/erros/integer-overflow-at-runtime-como-resolver-em-zig/"
markdown_url: "https://ziglang.com.br/erros/integer-overflow-at-runtime-como-resolver-em-zig.MD"
description: "Entenda o erro de overflow de inteiro em tempo de execução no Zig, quando operações aritméticas excedem os limites do tipo em runtime."
date: "2026-02-21"
author: "Zig Brasil"
---

# integer overflow at runtime — Como Resolver em Zig

Entenda o erro de overflow de inteiro em tempo de execução no Zig, quando operações aritméticas excedem os limites do tipo em runtime.


# integer overflow at runtime — Como Resolver em Zig

## O Que Este Erro Significa

O erro `integer overflow` em tempo de execução é um panic que ocorre quando uma operação aritmética produz um resultado que não cabe no tipo inteiro utilizado. Em builds Debug e ReleaseSafe, Zig verifica automaticamente todas as operações aritméticas para overflow e gera um panic quando detectado. Isso previne uma classe inteira de bugs silenciosos que existem em C/C++.

A mensagem de panic é:

```
thread 1 panic: integer overflow
```

## Diferença do Overflow em Comptime

O [overflow em comptime](/erros/erro-integer-overflow-comptime/) é sempre um erro de compilação. O overflow em runtime só é detectado em builds com verificações de segurança habilitadas (Debug e ReleaseSafe). Em ReleaseFast e ReleaseSmall, a verificação é removida para performance.

## Causas Comuns

### 1. Soma que Excede o Limite

```zig
pub fn main() void {
    var a: u8 = 250;
    a += 10; // PANIC: 250 + 10 = 260, que não cabe em u8 (max 255)
}
```

### 2. Multiplicação com Resultado Grande

```zig
pub fn main() void {
    var x: u16 = 1000;
    x *= 100; // PANIC: 1000 * 100 = 100000, não cabe em u16 (max 65535)
}
```

### 3. Subtração com Resultado Negativo em Unsigned

```zig
pub fn main() void {
    var saldo: u32 = 100;
    const debito: u32 = 150;
    saldo -= debito; // PANIC: 100 - 150 = -50, não representável em u32
}
```

### 4. Conversão com @intCast que Não Cabe

```zig
pub fn main() void {
    const grande: u32 = 300;
    const pequeno: u8 = @intCast(grande); // PANIC: 300 não cabe em u8
    _ = pequeno;
}
```

### 5. Loop com Contador que Estoura

```zig
pub fn main() void {
    var contador: u8 = 0;
    while (true) {
        contador += 1; // PANIC quando contador chega a 255 e tenta incrementar
        if (contador == 0) break; // Nunca alcançado em Debug
    }
}
```

### 6. Negação de Inteiro Mínimo em Signed

```zig
pub fn main() void {
    var x: i8 = -128;
    x = -x; // PANIC: -(-128) = 128, que não cabe em i8 (max 127)
}
```

## Como Corrigir

### Solução 1: Usar Tipo Maior

```zig
pub fn main() void {
    var x: u32 = 1000; // u32 ao invés de u16
    x *= 100; // OK: 100000 cabe em u32
    _ = x;
}
```

### Solução 2: Operações com Saturação (+|, -|, *|)

Operações saturantes limitam o resultado ao valor máximo ou mínimo do tipo:

```zig
pub fn main() void {
    var a: u8 = 250;
    a +|= 10; // Resultado: 255 (saturado no máximo)
    // a é 255, não causa panic

    var b: u8 = 5;
    b -|= 10; // Resultado: 0 (saturado no mínimo)
    _ = a;
    _ = b;
}
```

### Solução 3: Operações com Wrapping (+%, -%, *%)

Se o comportamento de wrap-around é o desejado:

```zig
pub fn main() void {
    var contador: u8 = 250;
    contador +%= 10; // Resultado: 4 (wrap around: 260 % 256 = 4)
    _ = contador;
}
```

### Solução 4: Verificar Antes de Operar

```zig
const std = @import("std");

pub fn main() void {
    var saldo: u32 = 100;
    const debito: u32 = 150;

    if (debito > saldo) {
        std.debug.print("Saldo insuficiente!\n", .{});
    } else {
        saldo -= debito; // Seguro: verificado antes
    }
    _ = saldo;
}
```

### Solução 5: Usar @addWithOverflow

```zig
const std = @import("std");

pub fn main() void {
    const a: u8 = 250;
    const b: u8 = 10;
    const resultado = @addWithOverflow(a, b);
    if (resultado[1] != 0) {
        std.debug.print("Overflow detectado!\n", .{});
    } else {
        std.debug.print("Resultado: {}\n", .{resultado[0]});
    }
}
```

### Solução 6: Usar math.add Para Verificação Segura

```zig
const std = @import("std");

pub fn main() void {
    const a: u8 = 250;
    const b: u8 = 10;
    const resultado = std.math.add(u8, a, b) catch {
        std.debug.print("Overflow!\n", .{});
        return;
    };
    std.debug.print("Resultado: {}\n", .{resultado});
}
```

## Operadores Aritméticos do Zig — Referência Rápida

| Operação     | Normal | Wrapping | Saturating |
|-------------|--------|----------|------------|
| Soma        | `+`    | `+%`     | `+\|`      |
| Subtração   | `-`    | `-%`     | `-\|`      |
| Multiplicação| `*`   | `*%`     | `*\|`      |
| Shift left  | `<<`   | `<<%`    | `<<\|`     |

## Comportamento por Build Mode

| Build Mode    | Overflow detectado? | Ação            |
|---------------|--------------------|--------------    |
| Debug         | Sim                | Panic + trace   |
| ReleaseSafe   | Sim                | Panic + trace   |
| ReleaseFast   | Não                | Wrap silencioso |
| ReleaseSmall  | Não                | Wrap silencioso |

## Dicas Práticas

1. **Sempre teste em Debug** — Overflow silencioso em Release pode esconder bugs
2. **Prefira tipos maiores** — Se não há restrição de memória, use `u32` ou `u64`
3. **Use saturação para contadores** — Contadores que não devem ultrapassar um limite
4. **Use wrapping para checksums** — Operações onde wrap-around é o comportamento desejado

## Erros Relacionados

- [integer overflow at comptime](/erros/erro-integer-overflow-comptime/) — Overflow em tempo de compilação
- [integer truncation](/erros/erro-truncation/) — Truncamento ao converter tipos
- [division by zero](/erros/erro-division-by-zero/) — Divisão por zero

## Links Úteis

- [Documentação oficial do Zig — Operators](https://ziglang.org/documentation/master/#Operators)
- [Zig Language Reference — Safety](https://ziglang.org/documentation/master/#Safety)
