← Debugging Guides

阅读中文版本

Rust: index out of bounds panic

Diagnose Rust "index out of bounds" panics from slicing and Vec indexing, and replace unchecked indexing with get or iterators.

intermediatedebuggingrustpanic

Symptoms

  • thread main panicked at index out of bounds: the len is 3 but the index is 5
  • A parser or loop panics only on short input
  • The panic points at v[i] or &slice[a..b]

Possible causes

  • Indexing a Vec or slice past its length
  • A slice range where start > end or end exceeds len
  • Off-by-one in a loop that iterates to len inclusive
  • Assuming a split or splitn produced more parts than it did

Diagnosis steps

Read the panic message for len and index

Interpretation

Both values identify whether the index is too high or the collection is shorter than expected.

Locate the indexing expression

Interpretation

The backtrace names the line; distinguish v[i] from a range slice.

Print the collection length before the access

Interpretation

If len is smaller than assumed, upstream parsing or filtering removed elements.

Root cause

Rust bounds-checks indexing at run time: accessing a Vec, slice, or array element outside its length panics rather than reading garbage. This is memory-safe but aborts the thread, so code that assumes a minimum size must validate input or use non-panicking accessors.

Fix

Use get(i) which returns Option, get(a..b) for safe slicing, and iterators like .iter().enumerate() instead of manual indices. Validate parsed sizes before slicing, and prefer first()/last() over split indexing. Where an index is guaranteed valid, an assertion with a clear message documents the invariant.

Verify the fix

Re-run the previously failing input under a test; no panic occurs and get returns Some for valid indices, with a test asserting None for out-of-range access.

Symptoms

The program panics with index out of bounds: the len is N but the index is M. It commonly appears on short or malformed input that a happy-path loop assumed would be long enough.

Diagnosis

Read the panic values and the offending expression:

let parts: Vec<_> = line.split(',').collect();
let name = &parts[2]; // panics when fewer than 3 fields

Add a length check to confirm the collection is shorter than assumed.

Fix

Use non-panicking accessors and iterators:

let name = parts.get(2).ok_or("missing field")?;

for (i, item) in items.iter().enumerate() {
    if i > 0 { /* safe: i < len */ }
}

Validate sizes before range slicing.

Verification

Run the failing input as a test asserting parts.get(2) is None rather than panicking; the parser returns a clear error and no bounds panic occurs.

Additional Notes

Rust bounds-checks indexing deliberately, so a panic here is memory safety working as designed rather than a low-level fault. Replacing indexing with an accessor that returns an optional value moves the failure from a crash to an ordinary error the caller can handle, which is usually what parsers and protocols want. Iterators remove most manual index arithmetic entirely, and when an index is provably valid, an assertion with a clear message documents the invariant and keeps the bounds check meaningful instead of redundant.