访问std::list元素将转储核心

Accessing std::list element gets core dumped

本文关键字:转储 核心 list std 访问 元素      更新时间:2023-10-16
#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);
}

我正在尝试模拟操作系统中最近最少使用的机制。但我想,如果你不知道的话,你仍然可以理解这个问题。

输入将是一系列假想的存储器地址,并且它们在整个程序中以string的形式被操纵。(我说的不是变量的地址或指针之类的。)每一行都包含一个地址,我用getline逐行读取。

我需要一直维护两个容器
第一个是地图,其类型为<string, list<string::iterator>>。这记录虚拟存储器中当前是否存在一个地址以及该地址在列表(第二个容器)中的位置
第二个是列表,其类型为list<string>。这样可以跟踪每个地址的"最近性"。最近的在后面,最近的在前面。

在获得一个地址后,如果该地址在映射中不存在(并且虚内存中仍然存在空格),则它将首先被push_back写入列表。然后,我会记录该元素在列表中的位置,制作pair<string, list<string::iterator>>(first是地址,second是位置),并将insert放入映射中。

如果想象中的内存已满,则弹出最近的内存并插入新的内存。两个容器都应进行维护。通过访问列表的前面,我知道哪一个是最近的。

如果映射中已经存在地址(命中),则列表中相应的数据将再次被erased和push_backed放入列表中,使其成为最新的数据。

问题就在这里

在运行输入时,有时我会得到核心转储。gdb告诉我问题总是在updateOrder中(我尝试了几种不同的重新排列代码的方法)。我想我没有很好地处理迭代器。

更有趣的是,如果我做runSimulation(64, fs),那么frameNum为64就可以了,核心转储为128。然而,如果我先做runSimulation(128, fs),它在128处会很好,但在256处会被丢弃。

runSimulation开始时的初始化过程中是否出现问题?或者迭代器指向错误的位置?

问题出现在updateOrder中。您可以擦除现有节点并创建一个新节点,但memory仍然有一个迭代器用于擦除的节点。您可以使用新位置更新memory,但更好的解决方案是使用splice:

void updateOrder(list<string>::iterator orderPos){
order.splice(order.back(), order, orderpos);
}

这将把现有节点移到列表的末尾,而不会使任何现有迭代器无效。

顺便说一句,当您分配一个字符串(您不使用)时,insertValue中的内存会泄漏。