krahets/hello-algo · error · IndexError

索引越界

Error message

索引越界

What it means

Raised by the get(index) accessor of the MyList teaching class (a hand-written dynamic array) when the caller requests a slot outside the valid element range [0, size). The guard 'index < 0 || index >= size' fires before the underlying @arr is touched, preventing undefined reads. It uses Ruby's built-in IndexError so callers can rescue it with a standard exception type.

Source

Thrown at zh-hant/codes/ruby/chapter_array_and_linkedlist/my_list.rb:23

=end

### 串列類別 ###
class MyList
  attr_reader :size       # 獲取串列長度(當前元素數量)
  attr_reader :capacity   # 獲取串列容量

  ### 建構子 ###
  def initialize
    @capacity = 10
    @size = 0
    @extend_ratio = 2
    @arr = Array.new(capacity)
  end

  ### 訪問元素 ###
  def get(index)
    # 索引如果越界,則丟擲異常,下同
    raise IndexError, "索引越界" if index < 0 || index >= size
    @arr[index]
  end

  ### 訪問元素 ###
  def set(index, num)
    raise IndexError, "索引越界" if index < 0 || index >= size
    @arr[index] = num
  end

  ### 在尾部新增元素 ###
  def add(num)
    # 元素數量超出容量時,觸發擴容機制
    extend_capacity if size == capacity
    @arr[size] = num

    # 更新元素數量
    @size += 1
  end

View on GitHub (pinned to 69932aed18)

Solutions

  1. Validate the index before calling: use 'if index >= 0 && index < list.size' as a guard.
  2. Use exclusive ranges (0...size) in iteration loops so the last valid index is size - 1, not size.
  3. Check list.size or call a helper before get to short-circuit on empty lists.
  4. Wrap the call in begin/rescue IndexError to handle the edge case gracefully when the index source is external or user-provided.

Example fix

# before
val = list.get(i)  # crashes when i == list.size in an inclusive loop

# after
val = (0...list.size).map { |i| list.get(i) }  # exclusive range, never hits size
Defensive patterns

Strategy: validation

Validate before calling

return nil unless index >= 0 && index < list.size
val = list.get(index)

Type guard

# Ruby: guard method for safe access
def safe_get(list, index)
  (index.is_a?(Integer) && index >= 0 && index < list.size) ? list.get(index) : nil
end

Try / catch

begin
  val = list.get(index)
rescue IndexError => e
  # handle out-of-bounds: log, use default, or re-raise with context
  val = nil
end

Prevention

When it happens

Trigger: Calling my_list.get(negative_number), calling get with an index equal to or greater than the current element count (my_list.size), or calling get on a freshly-constructed list (size == 0) with any index at all.

Common situations: Off-by-one loops using 0..size (inclusive) instead of 0...size (exclusive); confusing the backing array capacity with the logical element count; iterating a range that was computed against @arr.length rather than list.size; reading before any add() calls have populated the list.

Related errors


AI-assisted analysis of krahets/hello-algo@69932aed18 (2026-08-13). Data as JSON: /api/errors/ce9f925afe8adff3. Report an issue: GitHub.