---
title: "Panic: Index Out of Bounds no Rust"
url: "https://rustlang.com.br/erros/panic-index-out-of-bounds/"
markdown_url: "https://rustlang.com.br/erros/panic-index-out-of-bounds.MD"
description: "Como evitar o panic de index out of bounds no Rust ao acessar arrays e vetores. Aprenda a usar get(), iteradores, bounds checking e outras técnicas seguras."
date: "2026-02-23"
author: "Equipe Rust Brasil"
---

# Panic: Index Out of Bounds no Rust

Como evitar o panic de index out of bounds no Rust ao acessar arrays e vetores. Aprenda a usar get(), iteradores, bounds checking e outras técnicas seguras.


# Panic: Index Out of Bounds

O panic **"index out of bounds"** ocorre quando você tenta acessar um elemento de um array, slice ou `Vec` usando um índice que está **fora do intervalo válido**. É um erro de runtime que causa o encerramento imediato do programa.

## A Mensagem de Erro

```
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 5', src/main.rs:4:20
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

Variação com slices:

```
thread 'main' panicked at 'range end index 10 out of range for slice of length 3', src/main.rs:4:22
```

## O Que Significa

Arrays, slices e `Vec` no Rust são indexados a partir de **0**. Um vetor com 3 elementos tem índices válidos `0`, `1` e `2`. Acessar o índice `3` (ou qualquer índice >= comprimento) causa panic.

O Rust faz **bounds checking** (verificação de limites) em todo acesso por índice. Isso é diferente de C/C++, onde acessar fora dos limites causa **comportamento indefinido** silenciosamente. No Rust, o programa aborta com uma mensagem clara em vez de continuar com dados corrompidos.

Cenários comuns:
1. **Loop com índice errado** — `for i in 0..=len` (deveria ser `0..len`)
2. **Vetor vazio** — acessar `vec[0]` sem verificar se está vazio
3. **Off-by-one** — erro clássico de "um a mais" ou "um a menos"
4. **Índice calculado** — resultado de cálculo que excede o comprimento

## Código com Erro

```rust
fn main() {
    let numeros = vec![10, 20, 30];

    // PANIC: índice 3 não existe (válidos: 0, 1, 2)
    println!("{}", numeros[3]);

    // PANIC: vetor pode estar vazio
    let vazio: Vec<i32> = Vec::new();
    println!("{}", vazio[0]);

    // PANIC: off-by-one no loop
    for i in 0..=numeros.len() {  // =numeros.len() está fora
        println!("{}", numeros[i]);
    }

    // PANIC: slice fora dos limites
    let fatia = &numeros[1..5];
}
```

## Como Resolver

### Solução 1: Usar `.get()` para Acesso Seguro

O método `.get()` retorna `Option<&T>` — `None` se o índice for inválido:

```rust
fn main() {
    let numeros = vec![10, 20, 30];

    // Seguro: retorna None se não existir
    match numeros.get(5) {
        Some(valor) => println!("Valor: {}", valor),
        None => println!("Índice inválido"),
    }

    // Com unwrap_or para valor padrão
    let valor = numeros.get(5).unwrap_or(&0);
    println!("Valor: {}", valor);

    // if let para caso simples
    if let Some(primeiro) = numeros.get(0) {
        println!("Primeiro: {}", primeiro);
    }
}
```

Para slices, use `.get(range)`:

```rust
fn main() {
    let numeros = vec![10, 20, 30];

    // Seguro: retorna None se o range for inválido
    if let Some(fatia) = numeros.get(1..5) {
        println!("{:?}", fatia);
    } else {
        println!("Range inválido");
    }
}
```

### Solução 2: Usar Iteradores em Vez de Índices

Iteradores eliminam completamente o risco de index out of bounds:

```rust
fn main() {
    let numeros = vec![10, 20, 30, 40, 50];

    // Em vez de for i in 0..numeros.len(), use:
    for numero in &numeros {
        println!("{}", numero);
    }

    // Com índice se necessário
    for (i, numero) in numeros.iter().enumerate() {
        println!("[{}] = {}", i, numero);
    }

    // Processar pares de elementos adjacentes
    for par in numeros.windows(2) {
        println!("{} -> {}", par[0], par[1]);
    }

    // Processar em chunks
    for grupo in numeros.chunks(2) {
        println!("{:?}", grupo);
    }
}
```

### Solução 3: Verificar Limites Antes de Acessar

```rust
fn main() {
    let numeros = vec![10, 20, 30];
    let indice = 5;

    // Verificação explícita
    if indice < numeros.len() {
        println!("{}", numeros[indice]);
    } else {
        println!("Índice {} fora dos limites (max: {})", indice, numeros.len() - 1);
    }

    // Para primeiro/último elemento
    if let Some(primeiro) = numeros.first() {
        println!("Primeiro: {}", primeiro);
    }

    if let Some(ultimo) = numeros.last() {
        println!("Último: {}", ultimo);
    }

    // Verificar se não está vazio
    if !numeros.is_empty() {
        println!("Primeiro: {}", numeros[0]);
    }
}
```

### Solução 4: Usar `first()`, `last()` e Métodos Seguros

```rust
fn main() {
    let numeros = vec![10, 20, 30];

    // Métodos seguros que retornam Option
    let primeiro = numeros.first();     // Some(&10)
    let ultimo = numeros.last();        // Some(&30)

    // Para vetores mutáveis
    let mut dados = vec![1, 2, 3];
    if let Some(primeiro) = dados.first_mut() {
        *primeiro = 100;
    }
    println!("{:?}", dados); // [100, 2, 3]

    // pop() remove e retorna o último elemento
    let removido = dados.pop(); // Some(3)
    println!("Removido: {:?}", removido);
}
```

### Solução 5: Usar `saturating_sub` para Evitar Underflow em Índices

```rust
fn main() {
    let numeros = vec![10, 20, 30, 40, 50];
    let posicao: usize = 1;

    // Pegar elementos ao redor de uma posição
    let inicio = posicao.saturating_sub(2); // Não vai abaixo de 0
    let fim = (posicao + 3).min(numeros.len()); // Não passa do comprimento

    let vizinhos = &numeros[inicio..fim];
    println!("Vizinhos: {:?}", vizinhos);
}
```

## Padrão Comum: Processar Entrada do Usuário

```rust
fn buscar_item(lista: &[String], indice_str: &str) -> Option<&String> {
    let indice: usize = indice_str.parse().ok()?;
    lista.get(indice)
}

fn main() {
    let itens = vec![
        String::from("maçã"),
        String::from("banana"),
        String::from("laranja"),
    ];

    // Simula input do usuário
    let entrada = "1";

    match buscar_item(&itens, entrada) {
        Some(item) => println!("Item: {}", item),
        None => println!("Item não encontrado"),
    }
}
```

## Comparação de Abordagens

| Abordagem | Panic? | Uso recomendado |
|---|---|---|
| `vec[i]` | Sim, se fora | Quando o índice é garantido válido |
| `vec.get(i)` | Nao | Acesso com índice de fonte externa |
| `for item in &vec` | Nao | Iterar sobre todos os elementos |
| `vec.first()` / `vec.last()` | Nao | Acessar extremidades |
| `if i < vec.len()` | Nao | Verificação manual |

## Veja Também

- [Panic em unwrap(): Como Evitar](/erros/panic-unwrap/)
- [Panic: Stack Overflow](/erros/panic-stack-overflow/)
- [Tutorial de Tratamento de Erros](/tutoriais/tratamento-de-erros/)
- [Cheatsheet Rust](/cheatsheet/)
