C ++ exc_bad_access从unordered_map中的指向对象访问字符串字段

时间:2015-01-27 09:21:10

标签: c++ vector exc-bad-access unordered-map

我正在尝试以下列方式维护快速访问向量:

MyClass.h:

class MyClass{
private:
std::vector<Stuff> myStuffList;
std::tr1::unordered_map<std::string,Stuff*> myStuffListIndex;
...
public:
void addToStuffList(std::string key,Stuff stuff);

};

MyClass.cpp:

...
void MyClass::addToStuffList(std::string name, Stuff stuff){
  myStuffList.push_back(stuff);//our man is guaranteed to be at tail 
  myStuffListIndex[name] = &myStuffList[myStuffList.size()-1];//store 
  //pointer to object that we just copy-constructed at tail of list
}

Stuff.h:

class Stuff{
private:
  std::string name;
public:
  Stuff();
  Stuff(const Stuff&);
  Stuff& operator=(const Stuff&);
  ...

};

Stuff.cpp:

Stuff::Stuff() : name(""){}
Stuff::Stuff(const Stuff& other){
  if(this != &other){
    this->name = other.name;
  }
}
Stuff& Stuff::operator=(const Stuff& other){
  if(this != &other){
    this->name = other.name;
  }
}
std::string Stuff::getName(){
  return name;//exc_bad_access triggered here
}

稍后,当我尝试通过地图访问向量中的项目时,我得到一个明显间歇性的exc_bad_access错误,如下所示:

void methodA(){
  Stuff localStuff;
  myClassInstance.addToStuffList("mostrecentstuff",localStuff);
}
...
void methodB(){
  //different method now, localStuff would be out of scope but 
  //shouldn't matter since we passed by value in addToStuffList, right?
  Stuff* pStuff = myStuffListIndex["mostrecentstuff"];
  std::cout << "Hello, my name is " << pStuff->getName() << std::endl;
}

int main(int argc, const char* argv[]){
  methodA();
  methodB();
}

为什么访问pStuff-&gt; getName()会抛出exc_bad_access?

2 个答案:

答案 0 :(得分:1)

std::vector如何运作?
它有能力。当达到此容量并且您要求插入新项目时,将使用额外存储重新分配内存以保存此项目。 std::vector然后将其内容从第一个内存位置移动到新分配的位置。

因此,您的设计被破坏了(您需要在每个矢量调整大小时更新地图)。

然后,关于您的测试用例,由于您只执行一次插入,因此指向vector元素的指针仍然有效。但是看看你的addToStuffList()方法,我看到了:

void MyClass::addToStuffList(std::string name, Stuff stuff){
    myStuffList.push_back(ability);//our man is guaranteed to be at tail 
    myStuffListIndex[name] = &myStuffList[myStuffList.size()-1];//store 
    //pointer to object that we just copy-constructed at tail of list
}

不应该是:

myStuffList.push_back(stuff);

什么是ability

答案 1 :(得分:1)

如PaulMcKenzie所说,可以调整向量的大小,如果是,则可以在不同的地址重新定位。然后所有指向前一个矢量项的指针都会被破坏。

你永远不应该指向std容器中的项目,但是对于vector,你可以保留它们的索引。

你会:

std::vector<Stuff> myStuffList;
std::tr1::unordered_map<std::string,int> myStuffListIndex;

myStuffList.push_back(ability);//our man is guaranteed to be at tail 
myStuffListIndex[name] = myStuffList.size() - 1;//store 

如果您的应用程序是mutithreaded,则必须使用互斥锁保护上面的代码