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

时间:2018-12-27 04:32:32

标签: c++ iterator

#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开头的初始化期间出现问题吗?还是迭代器指向错误的位置?

1 个答案:

答案 0 :(得分:2)

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

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

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

偶然地,当您分配一个字符串(不使用)时,您在insertValue中泄漏了内存。