C++ exc_bad_access 从 unordered_map 中指向的对象访问字符串字段
C++ exc_bad_access accessing string field from pointed-to object in 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->getName() 会抛出 exc_bad_access?
std::vector
是如何工作的?
它有容量。当达到这个容量并且你要求插入一个新项目时,内存会重新分配额外的存储空间来容纳这个项目。 std::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
?
正如 PaulMcKenzie 所说,向量可以调整大小,如果可以,它可以重新定位到不同的地址。然后所有指向先前向量项的指针都被破坏了。
您永远不应保留指向 std 容器中项目的指针,但对于向量,您可以保留其索引。
你会:
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
如果您的应用程序是多线程的,则必须使用互斥锁来保护上述代码
我正在尝试通过以下方式维护快速访问向量:
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->getName() 会抛出 exc_bad_access?
std::vector
是如何工作的?
它有容量。当达到这个容量并且你要求插入一个新项目时,内存会重新分配额外的存储空间来容纳这个项目。 std::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
?
正如 PaulMcKenzie 所说,向量可以调整大小,如果可以,它可以重新定位到不同的地址。然后所有指向先前向量项的指针都被破坏了。
您永远不应保留指向 std 容器中项目的指针,但对于向量,您可以保留其索引。
你会:
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
如果您的应用程序是多线程的,则必须使用互斥锁来保护上述代码