繁体   English   中英

stl map <>中的分段错误

[英]Segmentation fault in stl map<>

我不是很擅长c ++,但我必须测试一个基于声誉的系统。 下面给出了一个代码片段,当我在ubuntu系统上运行它时,它给出了段错误。 正如我在评论中写的那样,两个函数“tackleFirstHandInfo()”和“updateReputation()”分别正确运行但是当我从另一个函数调用一个函数时它会崩溃。 任何帮助将不胜感激,提前感谢。 代码如下:

"ex.h"

#ifndef _ex_h
#define _ex_h
#include "iostream"
#include <map>
#define FADING 0.9
enum Behaviour {FORWARDING, NOTFORWARDING};

class Rating
{

private:
    double reputation;

public:

    Rating() { reputation = 5.0; }
    Rating(double rep) {reputation = rep;}

    ~Rating() {}

    double getRep() { return reputation; }

    void updateRep(Behaviour behaviour) {
        if (behaviour == FORWARDING)
            reputation = reputation + 1;    
        else 
            reputation = reputation - 1;    
    } 

};

#endif

"ex.cc"

#include <map>                                  
#include <string>
#include <iostream>   
#include "ex.h"                           
using namespace std;
typedef map<int, Rating*> ratingTable;
class RepSys {
private:
    ratingTable repTable; 
    map<int, Rating*> fHandInfo;
    Rating* rating;

public: 
    RepSys(){}
    ~RepSys(){}

    void tackleFirstHandInfo(int address, Behaviour behaviour)
    /* This Function and the function below individually run correctly */
    {
        map<int, Rating*>::iterator it;
        it=fHandInfo.find(address);
        if (it == fHandInfo.end()) {
            cout << "Adding New Entry for (fHandInfo) "<< address <<endl;
            rating = new Rating();   
            fHandInfo[address] = rating;
        }
        (it->second)->updateRep(behaviour);
        cout<<"First Hand Reputation of "<<address<<"\t is ="<< (it->second)->getRep()<<endl;
        updateReputation(address, behaviour); // This causes SegFault !!!!
        return;
    }

    void updateReputation(int address, Behaviour behaviour)
    {
        map<int, Rating*>::iterator it;
        it = repTable.find(address);
        if (it == repTable.end()) {
            cout << "Adding New Entry for (repTable) "<< address <<endl;
            rating = new Rating(); 
            repTable[address] = rating;
        }
        (it->second)->updateRep(behaviour);
        cout<<"Reputation of "<<address<<"\t is ="<< (it->second)->getRep()<<endl;
    }   
};

int main() {
    int address;    
    RepSys repsys;
    while (address != 0)
    {                                
        cout << "Address\n";
        cin >> address;
        repsys.tackleFirstHandInfo(address, FORWARDING);
    }
    return 0;
}

您在两个函数中都遇到了一个主要问题,它是:

if (it == fHandInfo.end()){
    // Some code that doesn't alter 'it'
}
(it->second)->updateRep(behaviour);

如果it确实指向最后那么它不是可解除引用的,所以it->second具有未定义的行为。 如果你要插入一些东西,希望it在它指向则必须重做find或使用返回一个迭代器的插入方法(或一对包括迭代器),并重新分配it的返回值的正确部分。

编辑

还有几点:

class RepSys {
private:
    ratingTable repTable; 
    map<int, Rating*> fHandInfo;
    Rating* rating;

您已经将typedef ed ratingTable设置为map<int, Rating*> 将typedef用于一个类变量而不是另一个变量似乎有点不一致。

rating是一个类变量,但您似乎只将它用作两个函数中的临时持有者。 如果这是您的预期用途,最好在两个函数中使用局部变量。

您永远不会delete放置在地图中的Rating对象。 如果映射应该拥有Rating对象,那么从对象生存期/内存管理的角度来看,使用std::map<int, Rating>会更容易std::map<int, Rating>这样您就不必进行任何手动删除。 似乎Rating不是基本调用,它是一个值类。

it = repTable.find(address);
if (it == repTable.end()){
cout << "Adding New Entry for (repTable) "<< address <<endl;
rating = new Rating(); 
repTable[address] = rating;
}
(it->second)->updateRep(behaviour);

//当在地图中找不到地址时,在插入迭代器后, it不会自动指向//新插入的元素。 因此,(它 - >第二个)是UB。

您可以稍微修改一下代码:

 Rating* rating = NULL;
map<int, Rating*>::iterator it = repTable.find(address);
if (it == repTable.end())
{
 rating = new Rating(); 
repTable[address] = rating;
}
else
{
 rating = it->second;
}

rating-> updateRep(行为);

与segfault略有不同,但是一个阻止您的示例正常工作的问题:在您的main函数中,您声明了address并且在使用它之前没有定义它。

int main() {
    int address;    
    RepSys repsys;
    while (address != 0)
    {
// ...
    }

在第一次运行时,根据您的编译器,您不知道address的值是什么。 起初,我无法将你的例子变成segfault,因为我的编译器初始化地址为0,它只是跳过循环并退出。

确保在使用变量之前初始化变量。

Seg故障通常是因为您尝试访问尚未分配的对象。

在您的代码中,您从IF()块中调用构造函数。

if (it == repTable.end()){
   cout << "Adding New Entry for (repTable) "<< address <<endl;
   rating = new Rating(); 
   repTable[address] = rating;
}

如果您尝试访问repTable [地址]并且没有对象,则即时异常。

尝试将其放入catch块并打印出异常详细信息。 这可能会为您提供有关导致问题的结构的更多信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM