---
title: "Panic: Stack Overflow no Rust"
url: "https://rustlang.com.br/erros/panic-stack-overflow/"
markdown_url: "https://rustlang.com.br/erros/panic-stack-overflow.MD"
description: "Como resolver stack overflow no Rust: causas como recursão infinita, tipos grandes na stack e soluções com iteração, Box, aumento de stack e trampolining."
date: "2026-02-23"
author: "Equipe Rust Brasil"
---

# Panic: Stack Overflow no Rust

Como resolver stack overflow no Rust: causas como recursão infinita, tipos grandes na stack e soluções com iteração, Box, aumento de stack e trampolining.


# Panic: Stack Overflow

O **stack overflow** ocorre quando o programa esgota o espaço disponível na **stack** (pilha de execução). As causas mais comuns são **recursão infinita** (ou muito profunda) e **tipos muito grandes** alocados na stack.

## A Mensagem de Erro

```
thread 'main' panicked at 'thread has overflowed its stack', src/main.rs:3:5

thread 'main' has overflowed its stack
fatal runtime error: stack overflow
```

Diferente de outros panics, o stack overflow pode não exibir um backtrace completo, pois não há espaço na stack nem para executar o handler de panic.

## O Que Significa

Todo programa tem uma **stack** — uma região de memória fixa (geralmente 8 MB no Linux, 1 MB no Windows) usada para:

- Variáveis locais de funções
- Parâmetros de funções
- Endereços de retorno (call stack)

Cada chamada de função adiciona um **stack frame** à pilha. Se a recursão for muito profunda ou se variáveis locais forem muito grandes, a stack transborda.

O Rust não tem **tail call optimization** (TCO) garantida pelo compilador, então mesmo recursão em posição final pode causar stack overflow com profundidade suficiente.

## Código com Erro

### Recursão Infinita

```rust
fn contar(n: u64) -> u64 {
    // Esqueceu o caso base — recursão infinita!
    contar(n + 1)
}

fn main() {
    println!("{}", contar(0)); // STACK OVERFLOW
}
```

### Recursão Muito Profunda

```rust
fn fatorial(n: u64) -> u64 {
    if n <= 1 {
        1
    } else {
        n * fatorial(n - 1) // Cada chamada usa mais stack
    }
}

fn main() {
    // Para n grande, estoura a stack
    println!("{}", fatorial(1_000_000)); // STACK OVERFLOW
}
```

### Tipo Grande na Stack

```rust
fn main() {
    // Array de 10 milhões de f64 = ~80 MB na stack
    let dados = [0.0_f64; 10_000_000]; // STACK OVERFLOW
    println!("Tamanho: {}", dados.len());
}
```

### Recursão Mútua

```rust
fn par(n: u64) -> bool {
    if n == 0 { true } else { impar(n - 1) }
}

fn impar(n: u64) -> bool {
    if n == 0 { false } else { par(n - 1) }
}

fn main() {
    println!("{}", par(1_000_000)); // STACK OVERFLOW
}
```

## Como Resolver

### Solução 1: Converter Recursão em Iteração

A solução mais eficaz — loops não consomem stack adicional:

```rust
fn fatorial(n: u64) -> u64 {
    let mut resultado: u64 = 1;
    for i in 2..=n {
        resultado = resultado.saturating_mul(i);
    }
    resultado
}

fn main() {
    println!("{}", fatorial(20)); // Funciona perfeitamente
}
```

Fibonacci iterativo:

```rust
fn fibonacci(n: u64) -> u64 {
    if n <= 1 {
        return n;
    }

    let mut a: u64 = 0;
    let mut b: u64 = 1;

    for _ in 2..=n {
        let temp = a + b;
        a = b;
        b = temp;
    }

    b
}

fn main() {
    println!("Fib(50) = {}", fibonacci(50));
}
```

### Solução 2: Usar `Box` para Alocar no Heap

Para dados grandes, use `Box<T>` que aloca no heap (sem limite de tamanho fixo):

```rust
fn main() {
    // Alocado no HEAP via Box — sem stack overflow
    let dados = vec![0.0_f64; 10_000_000];
    println!("Tamanho: {}", dados.len());

    // Ou com Box para arrays
    let array: Box<[f64]> = vec![0.0; 10_000_000].into_boxed_slice();
    println!("Tamanho: {}", array.len());
}
```

Para structs grandes:

```rust
struct DadosGrandes {
    buffer: Box<[u8; 1_000_000]>,  // 1 MB no heap
    nome: String,
}

impl DadosGrandes {
    fn novo(nome: String) -> Self {
        DadosGrandes {
            buffer: Box::new([0u8; 1_000_000]),
            nome,
        }
    }
}
```

### Solução 3: Aumentar o Tamanho da Stack

Para threads específicas, defina um tamanho de stack maior:

```rust
use std::thread;

fn recursao_profunda(n: u64) -> u64 {
    if n <= 1 { 1 } else { n + recursao_profunda(n - 1) }
}

fn main() {
    // Thread com 64 MB de stack
    let builder = thread::Builder::new().stack_size(64 * 1024 * 1024);

    let handler = builder.spawn(|| {
        println!("{}", recursao_profunda(500_000));
    }).unwrap();

    handler.join().unwrap();
}
```

**Nota:** Aumentar a stack é um paliativo, não uma solução. Prefira converter para iteração.

### Solução 4: Técnica de Trampolining

Para manter o estilo recursivo sem estourar a stack:

```rust
enum Trampolim<T> {
    Feito(T),
    Continuar(Box<dyn FnOnce() -> Trampolim<T>>),
}

fn executar<T>(mut t: Trampolim<T>) -> T {
    loop {
        match t {
            Trampolim::Feito(valor) => return valor,
            Trampolim::Continuar(f) => t = f(),
        }
    }
}

fn fatorial_tramp(n: u64, acumulador: u64) -> Trampolim<u64> {
    if n <= 1 {
        Trampolim::Feito(acumulador)
    } else {
        Trampolim::Continuar(Box::new(move || {
            fatorial_tramp(n - 1, n * acumulador)
        }))
    }
}

fn main() {
    let resultado = executar(fatorial_tramp(100_000, 1));
    println!("Concluído");
}
```

### Solução 5: Usar Stack Explícita (Simulação de Recursão)

Substitua a call stack por uma estrutura de dados explícita:

```rust
fn percorrer_arvore(raiz: Option<Box<No>>) {
    let mut pilha = Vec::new();

    if let Some(no) = raiz {
        pilha.push(no);
    }

    while let Some(no) = pilha.pop() {
        println!("{}", no.valor);

        if let Some(direita) = no.direita {
            pilha.push(direita);
        }
        if let Some(esquerda) = no.esquerda {
            pilha.push(esquerda);
        }
    }
}

struct No {
    valor: i32,
    esquerda: Option<Box<No>>,
    direita: Option<Box<No>>,
}
```

## Quando Usar Cada Solução

| Problema | Solução recomendada |
|---|---|
| Recursão simples (fatorial, soma) | Converter para loop |
| Traversal de árvore/grafo | Stack explícita com `Vec` |
| Array/struct grande | `Vec`, `Box`, ou alocação no heap |
| Recursão inevitável e profunda | Aumentar stack da thread |
| Manter estilo funcional | Trampolining |

## Veja Também

- [Panic em unwrap(): Como Evitar](/erros/panic-unwrap/)
- [Panic: Index Out of Bounds](/erros/panic-index-out-of-bounds/)
- [Tutorial de Tratamento de Erros](/tutoriais/tratamento-de-erros/)
- [Glossário Rust](/glossario/)
