在我的程序中,我试图取消对结构文章的指针的引用,以获取其ID,但我得到的是“访问冲突读取位置0xCCCCCCCC”。我尝试了许多不同的事情,局部变量,将指针回溯到代码中,使用不同的括号……尽管没有。我没有选择余地,但是无论我怎么努力,我都看不到问题。
这个问题可能有一个答案,但是访问冲突对我来说太笼统了,无法找到我要寻找的答案(大多数问题都围绕数组,这不是我的情况)
在这里,我定义了一个简单的结构来保存我的数据。
struct Article {
public:
std::string id;
std::string title;
std::string text;
Article(std::string article_id, std::string article_title, std::string article_text) : id(article_id), title(article_title), text(article_text) {};
void toString();
};
接下来,我使用字典将所有单词映射到它们出现的文章。代码本身并没有完成,但是单词映射应该包括所有必要的指针。
std::map<std::string, std::map<Article*, unsigned>> word_dict_;
在保留所有vector<Article> articles_
的同时,我还要保留另一个void fulltext::generateDict() {
for (Article ar : articles_) {
unsigned wordStart;
bool isBuilding = false;
string buffer = "";
for (unsigned int it = 0; it <= ar.text.size(); ++it) {
char c;
if (it < ar.text.size())
c = ar.text.at(it);
else
c = '\0';
if (isalpha(c)) {
// start or middle of word
if (!isBuilding) {
isBuilding = true;
wordStart = it;
}
buffer += c;
}
else {
isBuilding = false;
if (buffer != "") {
stringToLower(buffer); // rewrites buffer to low case
// Here I tried creating &ar just for the laughs and it works just fine.
word_dict_[buffer][&ar] = wordStart;
buffer = "";
}
}
}
}
}
,因此word_dict_中不应出现空指针;
在这里生成字典。
void fulltext::printWordDict() {
cout << "Printing generated word dictionary: " << endl;
for (auto wordPair : word_dict_) {
cout << " \" " << wordPair.first << " \" " << endl;
cout << "There are " << wordPair.second.size() << " inputs." << endl;
for (pair<Article*, unsigned int> articlePair : wordPair.second) {
cout << (articlePair.first)->id << endl; // Here the access violation occurs
// Nothing seemingly works
// cout << articlePair.first->id; ... Access violation
// cout << (*articlePair.first).id; ... Access violation
// auto ar = articlePair.first; cout << ar->id; ... access violation
// auto ar = articlePair.first; cout << (*ar).id; ... access again
}
cout << endl;
}
cout << "Done." << endl;
}
最后但并非最不重要的一点,我想将其打印出来,然后真正的乐趣就开始了。
fulltext::proccess()
从主函数cordova android build --stagging
内部立即连续调用这些函数。 word_dict_是类私有变量。
如果需要代码的其他任何部分,请告诉我,尽管在这种情况下,其他任何问题都不会出现。
答案 0 :(得分:4)
for (Article ar : articles_) {
...
word_dict_[buffer][&ar] = wordStart;
...
}
这里,您在字典中存储了指向ar
的指针,但是ar
在其作用域的末尾被破坏-当for循环结束时。因此,现在您在地图中存储了一个悬空指针,无法取消引用。
将Article
对象存储在地图中而不是Article*
,否则,只要您在地图中有指向该对象的指针,请确保Article
对象存在。
如果对象保存在articles_
容器中,则可能不需要在for循环中复制它,而是执行以下操作:
for (Article& ar : articles_) {
..
word_dict_[buffer][&ar] = wordStart;
现在,您将获得一个指向Article
中的article_
对象的指针。
尽管稍后会知道对article_
的处理方式-如果对其执行移动对象的操作(根据容器类型的不同,可能会发生多种原因),则word_dict_
中的指针变得无效。
答案 1 :(得分:4)
for (Article ar : articles_)
这会执行您的文章的副本,作为局部变量。一旦循环的下一次迭代出现,此局部变量就会超出范围。
word_dict_[buffer][&ar] = wordStart;
这里存储了指向局部变量的指针,该指针仅在循环内部有效。
如果可以确保您的文章将在地图上过期,则可以存储指向articles_
中存储的文章的指针。请注意,如果articles_
是std::vector
,则在您向其中插入新文章时可能会对其进行重新分配,因此必须小心地将指向对象的指针存储在其中,并确保在std::vector
发生了变化。
如果以上所有听起来都像您喝杯茶,那么您很可能想创建对本文的引用,就像这样
for (Article& ar : articles_)
使您的word_dict_
映射存储Article
对象通过Value代替指针。这种方法的缺点是您将文章存储两次,这具有逻辑上的含义(对地图内部文章的更改不会反映在articles_
向量中,反之亦然)以及内存方面的影响(您使用内存翻倍)
使您的articles_
向量存储区std::unique_ptr<Article>
。这样,您将无需手动管理向量内部的重新分配。您仍然需要管理从articles_
向量中删除文章的情况,并确保将其从word_dict_
地图中删除。这种方法的缺点是,默认情况下它会使您的类无法复制(std::unique_ptr
的副本构造函数已删除),这可能对您或不是您的问题。如果需要复制它们,则需要手动提供复制控制器和复制分配运算符,以及手动实现或= default
或其他3个特殊成员函数(请参见Rule of 5)