要让c++模拟的fifo页面置换算法输出可信命中率,必须同步维护队列与驻留集合、严格校验framecount边界、以总访问次数为固定分母;仅用std::queue会漏判命中,不擦除inmemory导致假缺页,剔除初始访问使结果失真。

要让C++模拟的FIFO页面置换算法输出可信的命中率,必须解决驻留状态判断失效、淘汰逻辑脱节、统计口径失真三大硬伤——只用std::queue会漏判所有命中,不校验frameCount边界会导致程序崩溃,把前几次访问从分母中剔除会让结果完全不可比。
同步维护队列与驻留集合
单独用std::queue无法判断页是否已在内存中,因为它的接口不支持查找;每次缺页都盲目装入,旧页号还残留在逻辑集合里,同一页面连续访问(如0 0 0)第二次起全判为缺页。这一步不是“推荐搭配”,是强制闭环。
方法一:std::queue + std::unordered_set原子对齐
① 声明两个容器:std::queue<int> pageQueue;</int> 和 std::unordered_set<int> inMemory;</int>,二者初始均为空。
② 每次访问页号page前,只查集合:if (inMemory.find(page) != inMemory.end()) → 命中则跳过全部置换逻辑,不碰queue,不增pageFaults。
③ 缺页时先执行pageFaults++,再检查if (pageQueue.size() == frameCount);仅当满帧才淘汰。
④ 淘汰必须成对:int victim = pageQueue.front(); pageQueue.pop(); inMemory.erase(victim); —— 【漏掉inMemory.erase(victim)会导致“幽灵页号”持续触发假缺页】。
⑤ 装入也必须成对:pageQueue.push(page); inMemory.insert(page);。
手写循环数组替代STL队列
适用于嵌入式或需控制内存布局的场景,但比STL更易出错。核心是cur指针只代表“下次该覆盖的位置”,不是“当前最老页索引”——最老页永远在frames[cur]。
第一步:分配固定帧数组:std::vector<int> frames(frameCount, -1);</int>,大小必须严格等于frameCount,多一分可能覆盖相邻变量,少一分导致cur越界写入。
第二步:初始化int cur = 0;,注意不能是未定义值或-1——C++中-1 % m仍是负数,直接越界。
第三步:仅在发生缺页且inMemory.size() == frameCount时,才执行cur = (cur + 1) % frameCount;。首次装入阶段(内存未满)绝不能动cur,否则最早装入的页会被跳过淘汰。
第四步:淘汰前取int victim = frames[cur];,装入后写frames[cur] = page;,再更新cur。同步维护inMemory:淘汰前inMemory.erase(victim),装入后inMemory.insert(page)。
命中率计算必须绑定总访问次数
操作系统级定义:命中率 = (总访问次数 − 缺页次数) / 总访问次数。这个分母就是原始输入序列长度,一个都不能少。有人误把“填空闲帧”的前frameCount次访问过滤掉,结果分子分母同时偏移,数值彻底失真。
方法1:直接用输入序列size作为分母
int totalAccesses = pageReferences.size(); → 全程固定不变,绝不修改。
方法2:在主循环外声明计数器并自增
int accessCount = 0; → 每次进入for循环体第一行就执行accessCount++,确保哪怕序列含非法页号(如负数),只要进了循环就算一次访问。
注意:【跳过初始装入阶段、对序列去重、截断冷启动访问,都会让命中率不可比】。真实OS的pagefault计数器就是从第一次访存开始累加的。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











