#include <iostream>
#include <string>
#include <fstream>
#include <list>
#include <map>
#include <iomanip>
using namespace std;
void runSimulation(int frameNum, fstream &fs);
void handleMemory(string address);
void handleAddress(int frameNum, string address);
void insertValue(string index);
void replaceValue(string index);
void updateOrder(list<string>::iterator orderPos);
int hit_num = 0, miss_num = 0;
const int INDEX_BITS = 5;
typedef map< string, list<string>::iterator > Memory;
typedef pair< string, list<string>::iterator > MemPair;
Memory memory;
list<string> order;
int main(){
fstream fs;
fs.open("trace.txt", fstream::in);
cout << "LRU---" << endl;
cout << left << setw(10) << "size";
cout << left << setw(15) << "miss";
cout << left << setw(20) << "hit";
cout << "page fault ratio" << endl;
for(int i=256; i<=512; i*=2){
runSimulation(i, fs);
fs.clear();
fs.seekg(0, ios::beg);
}
fs.close();
return 0;
}
void runSimulation(int frameNum, fstream &fs){
memory.clear();
order.clear();
hit_num = 0;
miss_num = 0;
string str;
while(getline(fs, str)){
handleAddress(frameNum, str);
}
cout << left << setw(10) << frameNum;
cout << left << setw(15) << miss_num;
cout << left << setw(20) << hit_num;
cout << fixed << setprecision(9) << (double)miss_num/(miss_num + hit_num) << endl;
}
void handleAddress(int frameNum, string address){
string index;
Memory::iterator found;
index = address.substr(0, INDEX_BITS);
found = memory.find(index);
if(found == memory.end()){ // miss
miss_num++;
if(memory.size() < frameNum){ // there are empty spaces
insertValue(index);
}
else{
replaceValue(index);
}
}
else{ // hit
hit_num++;
//cout << "hit: " << found->first << endl;
updateOrder(found->second);
}
}
void insertValue(string index){
//cout << "insert: " << index << endl;
string *newIndex = new string;
order.push_back(index);
list<string>::iterator it = order.end();
it--;
memory.insert(MemPair(index, it));
}
void replaceValue(string index){
//cout << "replace: " << index << endl;
memory.erase(order.front());
order.pop_front();
insertValue(index);
}
void updateOrder(list<string>::iterator orderPos){
string value = *orderPos;
order.erase(orderPos);
order.push_back(value);
}
我正在尝试模拟OS中最近最少使用的机制。但是我想,如果您不了解该问题,您仍然可以理解。
输入将是一系列虚构的存储器地址,并且它们在整个程序中都以string
的形式进行操作。 (我不是在说变量的地址或指针或其他东西。)每一行包含一个地址,我使用getline
逐行读取它们。
我一直需要维护两个容器。
第一个是地图,其类型为<string, list<string::iterator>>
。这个
记录虚拟内存中当前是否存在一个地址,以及该地址在列表(第二个容器)中的位置。
第二个是列表,其类型为list<string>
。这会跟踪每个地址的“最新性”。最新的一个在后面,而最少的一个在前面。
获得一个地址后,如果该地址在地图中不存在(并且虚内存中仍然存在空白),则将其首先push_back
放入列表。然后,我将记录该元素在列表中的位置,制作一个pair<string, list<string::iterator>>
(first
是地址,second
是位置),然后将insert
放入地图中
如果虚拟内存已满,请弹出最近的一个,然后插入新的。两个容器都应维护。通过访问列表的开头,我知道哪一个是最近的。
如果地图中已经存在一个地址(命中),则列表中的相应数据将被erase
d并再次push_back
进入列表,使其成为最新地址。 / p>
这是问题所在。
运行输入时,有时会发生核心转储。 gdb告诉我问题始终出在updateOrder
中(我尝试了几种不同的方式来重新排列代码)。我想我对迭代器的处理不太好。
更有趣的是,如果我做runSimulation(64, fs)
,将frameNum
设为64,将内核转储为128是可以的。但是,如果我先做runSimulation(128, fs)
,可以在128处罚款,但在256处倾销。
在runSimulation
开头的初始化期间出现问题吗?还是迭代器指向错误的位置?
答案 0 :(得分:2)
问题出在updateOrder
中。您删除了现有节点并创建了一个新节点,但是memory
仍然具有一个用于删除节点的迭代器。您可以使用新位置更新memory
,但是更好的解决方案是使用splice
:
void updateOrder(list<string>::iterator orderPos){
order.splice(order.back(), order, orderpos);
}
这会将现有节点移动到列表的末尾,而不会使任何现有迭代器无效。
偶然地,当您分配一个字符串(不使用)时,您在insertValue
中泄漏了内存。