Python动态分区内存分配GUI程序出现IndexError问题求助
动态内存分配模拟程序IndexError排查与修复
问题概述
开发带GUI的Python动态内存分配模拟程序时,触发IndexError: list index out of range错误,报错位置在allocate_memory方法的self.jobs[block_idx] -= process_size行。
报错堆栈
PS C:\Users\Admin> & C:/Users/Admin/AppData/Local/Microsoft/WindowsApps/python3.11.exe "c:/Users/Admin/Downloads/# Simple Python code.py" Exception in Tkinter callback Traceback (most recent call last): File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.1776.0_x64__qbz5n2kfra8p0\Lib\tkinter\__init__.py", line 1948, in __call__ return self.func(*args) ^^^^^^^^^^^^^^^^ File "c:\Users\Admin\Downloads\# Simple Python code.py", line 108, in allocate_memory self.memory_simulation.allocate_memory(algorithm) File "c:\Users\Admin\Downloads\# Simple Python code.py", line 40, in allocate_memory self.jobs[block_idx] -= process_size ~~~~~~~~~^^^^^^^^^^^ IndexError: list index out of range
原代码
import tkinter as tk from tkinter import ttk class MemoryAllocationSimulation: def __init__(self, memory_size, os_size, initial_jobs): self.memory_size = memory_size self.os_size = os_size self.free_memory = memory_size - os_size self.jobs = initial_jobs self.allocation = [-1] * (len(initial_jobs) + 10) # Adjust the size for potential new jobs def best_fit(self, process_size): best_idx = -1 for j in range(len(self.jobs) + 1): # Include free memory as a potential block if j == len(self.jobs): # Check for free memory if self.free_memory >= process_size: return j elif self.jobs[j] >= process_size: if best_idx == -1 or self.jobs[best_idx] > self.jobs[j]: best_idx = j return best_idx def allocate_memory(self, algorithm): # Allocate memory for existing jobs for i in range(len(self.jobs)): process_size = self.jobs[i] if algorithm == "best_fit": block_idx = self.best_fit(process_size) elif algorithm == "first_fit": block_idx = self.first_fit(process_size) elif algorithm == "worst_fit": block_idx = self.worst_fit(process_size) else: raise ValueError("Invalid memory allocation algorithm") if block_idx != -1: self.allocation[i] = block_idx self.free_memory -= process_size self.jobs[block_idx] -= process_size else: print(f"Job {i + 1} not allocated due to insufficient memory") # Allocate memory for new jobs new_jobs = [5, 30] for new_job in new_jobs: if algorithm == "best_fit": block_idx = self.best_fit(new_job) elif algorithm == "first_fit": block_idx = self.first_fit(new_job) elif algorithm == "worst_fit": block_idx = self.worst_fit(new_job) else: raise ValueError("Invalid memory allocation algorithm") if block_idx != -1: new_job_idx = len(self.jobs) + len(new_jobs) - 2 # Index for new jobs self.allocation[new_job_idx] = block_idx self.free_memory -= new_job self.jobs.append(new_job) # Append new jobs to the list self.jobs[block_idx] -= new_job else: print(f"New job {new_job} not allocated due to insufficient memory") new_job_idx = len(self.jobs) + len(new_jobs) - 2 # Index for new jobs self.allocation[new_job_idx] = -1 def first_fit(self, process_size): for j in range(len(self.jobs)): if self.jobs[j] >= process_size: return j return -1 def worst_fit(self, process_size): worst_idx = -1 for j in range(len(self.jobs)): if self.jobs[j] >= process_size: if worst_idx == -1 or self.jobs[worst_idx] < self.jobs[j]: worst_idx = j return worst_idx class MemoryAllocationGUI: def __init__(self, root): self.root = root self.root.title("Memory Allocation Simulation") self.memory_simulation = MemoryAllocationSimulation(100, 5, [15, 20]) self.algorithm_label = ttk.Label(root, text="Select Allocation Algorithm:") self.algorithm_label.pack(pady=10) self.algorithm_var = tk.StringVar() self.algorithm_var.set("best_fit") self.algorithm_combobox = ttk.Combobox(root, textvariable=self.algorithm_var, values=["best_fit", "first_fit", "worst_fit"]) self.algorithm_combobox.pack(pady=10) self.allocate_button = ttk.Button(root, text="Allocate Memory", command=self.allocate_memory) self.allocate_button.pack(pady=10) self.tree = ttk.Treeview(root, columns=('Job', 'Size', 'Block')) self.tree.heading('#0', text='Process No.') self.tree.heading('Job', text='Process Size') self.tree.heading('Size', text='Block No.') self.tree.pack(pady=10) def allocate_memory(self): algorithm = self.algorithm_var.get() self.memory_simulation.allocate_memory(algorithm) self.display_memory_status() def display_memory_status(self): self.tree.delete(*self.tree.get_children()) for i in range(len(self.memory_simulation.jobs)): process_size = self.memory_simulation.jobs[i] block_no = self.memory_simulation.allocation[i] + 1 if self.memory_simulation.allocation[i] != -1 else "Not Allocated" self.tree.insert('', i, text=f'Job {i + 1}', values=(process_size, block_no)) free_memory = self.memory_simulation.free_memory self.tree.insert('', len(self.memory_simulation.jobs), text='Free Memory', values=(free_memory, '')) if __name__ == "__main__": root = tk.Tk() gui = MemoryAllocationGUI(root) root.mainloop()
错误原因分析
- 索引超出范围:
best_fit方法中,当j == len(self.jobs)时直接返回该索引,而self.jobs的最大有效索引是len(self.jobs)-1,后续操作self.jobs[block_idx]必然触发越界。 - 逻辑混淆:原代码将待分配作业和内存块合并在
jobs列表中,导致分配逻辑混乱,新作业索引计算错误(new_job_idx = len(self.jobs) + len(new_jobs) - 2)。 - 空闲内存处理错误:使用空闲内存分配时,未将空闲内存转换为实际内存块,直接操作无效索引。
修复后代码
import tkinter as tk from tkinter import ttk class MemoryAllocationSimulation: def __init__(self, memory_size, os_size, initial_jobs): self.memory_size = memory_size self.os_size = os_size # 内存块列表:初始为空闲块,待分配作业单独存储 self.memory_blocks = [memory_size - os_size - sum(initial_jobs)] self.jobs_to_allocate = initial_jobs.copy() self.allocation = [-1] * (len(initial_jobs) + 10) # 预留新作业空间 def best_fit(self, process_size): best_idx = -1 for j in range(len(self.memory_blocks)): if self.memory_blocks[j] >= process_size: if best_idx == -1 or self.memory_blocks[best_idx] > self.memory_blocks[j]: best_idx = j return best_idx def allocate_memory(self, algorithm): # 添加新作业 self.jobs_to_allocate.extend([5, 30]) # 遍历所有待分配作业 for idx, process_size in enumerate(self.jobs_to_allocate): if algorithm == "best_fit": block_idx = self.best_fit(process_size) elif algorithm == "first_fit": block_idx = self.first_fit(process_size) elif algorithm == "worst_fit": block_idx = self.worst_fit(process_size) else: raise ValueError("Invalid memory allocation algorithm") if block_idx != -1: self.allocation[idx] = block_idx # 分配内存:减少块大小,剩余为0则删除该块 self.memory_blocks[block_idx] -= process_size if self.memory_blocks[block_idx] == 0: del self.memory_blocks[block_idx] # 更新后续作业的块索引 for i in range(idx + 1, len(self.allocation)): if self.allocation[i] > block_idx: self.allocation[i] -= 1 else: print(f"Job {idx + 1} ({process_size} units) not allocated due to insufficient memory") def first_fit(self, process_size): for j in range(len(self.memory_blocks)): if self.memory_blocks[j] >= process_size: return j return -1 def worst_fit(self, process_size): worst_idx = -1 for j in range(len(self.memory_blocks)): if self.memory_blocks[j] >= process_size: if worst_idx == -1 or self.memory_blocks[worst_idx] < self.memory_blocks[j]: worst_idx = j return worst_idx class MemoryAllocationGUI: def __init__(self, root): self.root = root self.root.title("Memory Allocation Simulation") # 初始化:内存总100,OS占5,初始待分配作业[15,20],初始空闲内存60 self.memory_simulation = MemoryAllocationSimulation(100, 5, [15, 20]) self.algorithm_label = ttk.Label(root, text="选择分配算法:") self.algorithm_label.pack(pady=10) self.algorithm_var = tk.StringVar() self.algorithm_var.set("best_fit") self.algorithm_combobox = ttk.Combobox(root, textvariable=self.algorithm_var, values=["best_fit", "first_fit", "worst_fit"]) self.algorithm_combobox.pack(pady=10) self.allocate_button = ttk.Button(root, text="分配内存", command=self.allocate_memory) self.allocate_button.pack(pady=10) # 作业分配状态视图 self.job_tree = ttk.Treeview(root, columns=('JobSize', 'BlockIndex')) self.job_tree.heading('#0', text='作业编号') self.job_tree.heading('JobSize', text='作业大小') self.job_tree.heading('BlockIndex', text='分配块索引') self.job_tree.pack(pady=10) # 内存块状态视图 self.block_tree = ttk.Treeview(root, columns=('BlockSize', 'Status')) self.block_tree.heading('#0', text='内存块编号') self.block_tree.heading('BlockSize', text='块大小') self.block_tree.heading('Status', text='状态') self.block_tree.pack(pady=10) def allocate_memory(self): algorithm = self.algorithm_var.get() # 重置模拟状态,避免重复分配 self.memory_simulation = MemoryAllocationSimulation(100, 5, [15, 20]) self.memory_simulation.allocate_memory(algorithm) self.display_memory_status() def display_memory_status(self): # 清空视图 self.job_tree.delete(*self.job_tree.get_children()) self.block_tree.delete(*self.block_tree.get_children()) # 显示作业分配状态 for idx, job_size in enumerate(self.memory_simulation.jobs_to_allocate): block_idx = self.memory_simulation.allocation[idx] block_text = str(block_idx + 1) if block_idx != -1 else "未分配" self.job_tree.insert('', idx, text=f'作业 {idx + 1}', values=(job_size, block_text)) # 显示内存块状态 for idx, block_size in enumerate(self.memory_simulation.memory_blocks): self.block_tree.insert('', idx, text=f'块 {idx + 1}', values=(block_size, '空闲')) if __name__ == "__main__": root = tk.Tk() gui = MemoryAllocationGUI(root) root.mainloop()
关键修正说明
- 分离作业与内存块:将待分配作业和内存块分开存储,避免逻辑混淆,从根源解决索引越界问题。
- 修复空闲内存处理:空闲内存作为独立内存块存在,分配后自动调整块大小或删除空块,同时更新后续作业的块索引。
- 重置模拟状态:每次分配前重置模拟实例,避免重复分配导致的逻辑错误。
- 优化GUI显示:新增内存块状态视图,更直观展示内存分配结果。
内容的提问来源于stack exchange,提问作者newbie
相关产品推荐
相关产品推荐

