我不是很擅长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;
}
答案 0 :(得分:10)
你在两个函数中都遇到了一个主要问题,那就是:
if (it == fHandInfo.end()){
// Some code that doesn't alter 'it'
}
(it->second)->updateRep(behaviour);
如果it
确实指向最后,那么它不是可解除引用的,因此it->second
具有未定义的行为。如果要插入某些内容并希望it
指向它,则必须重做find
或使用返回迭代器的插入方法(或包含迭代器的对)并重新分配{ {1}}返回值的正确部分。
修改强>
还有几点:
it
您已class RepSys {
private:
ratingTable repTable;
map<int, Rating*> fHandInfo;
Rating* rating;
感谢typedef
为ratingTable
。将typedef用于一个类变量而不是另一个变量似乎有些不一致。
map<int, Rating*>
是一个类变量,但您似乎只是将它用作两个函数中的临时持有者。如果这是您的预期用途,最好在两个函数中使用局部变量。
您不会rating
放置在地图中的delete
个对象。如果映射应该拥有Rating
个对象,那么从对象生存期/内存管理的角度来看,使用Rating
会更容易,因此您不必进行任何手动删除。 std::map<int, Rating>
似乎不是基本调用,它是一个值类。
答案 1 :(得分:2)
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
将不会自动指向//新插入的元素。因此,(it->; second)是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-&GT; updateRep(行为);
答案 2 :(得分:1)
与段错误略有不同,但是一个阻止您的示例正常工作的问题:在您的main函数中,您声明address
并且在使用之前没有定义它。
int main() { int address; RepSys repsys; while (address != 0) { // ... }
在第一次运行时,根据您的编译器,您不知道address
的值是什么。起初,我无法将你的例子变为segfault,因为我的编译器在0处初始化地址,它只是跳过循环并退出。
确保在使用之前初始化变量。
答案 3 :(得分:0)
Seg错误通常是因为您尝试访问尚未分配的对象。
在代码中,您从IF()块中调用构造函数。
if (it == repTable.end()){
cout << "Adding New Entry for (repTable) "<< address <<endl;
rating = new Rating();
repTable[address] = rating;
}
如果您尝试访问repTable [地址]并且没有对象,则即时异常。
尝试将其放入catch块并打印出异常详细信息。这可能会为您提供有关导致问题的结构的更多信息。