【问题标题】:Output to file giving wrong pointer values输出到文件给出错误的指针值
【发布时间】:2013-04-20 02:59:53
【问题描述】:

我有一个 Word 类,它包含一个字符串和一个结构向量,每个结构都包含一个指向容器类的指针,如下所示:

struct doc {
    Document* d;
    int timesMentioned = 0;
};

我有一个输出函数,可以输出每个 Word 的字符串和 Word 的 doc 向量中的每个 doc 的键。 (d1、d2、d3 等)

每当我将它们全部输出到文件时,它看起来像这样:

foo = d3,
bar = d3,
foobar = d3,
etc.

每个 Word 仅输出 d3(从给定输入文件循环遍历的最后一个文档。如果需要,我可以发布代码)

奇怪的是,每当我将它输出到控制台时,它都能正常工作。与每个 Word 关联的文档正确输出。知道为什么会发生这种情况吗?我认为它可能是一个悬空指针,但它正确输出到控制台很奇怪。如果需要,我可以发布添加文档功能或更多代码。

这是 Word 类的代码:

void Word::createWord(string str) {
    removePunctuation(str);
    toLower(str);
    word = str;
}
void Word::addDoc(Document& d) {
    doc newDoc;
    newDoc.d = &d;
    newDoc.timesMentioned++;
    docs.push_back(newDoc);
}
vector<doc> Word::getDocs() {
    return docs;
}
string Word::getWord() {
    return word;
}

//Formatting the string, should be irrelevant to this question
void Word::removePunctuation(string& str) {
    string temp = "";
    for(int i = 0; i < str.length(); i++) {
        bool punctual = false;
        for(int k = 0; k < 42; k++)
            if(str[i] == punctuals[k]) punctual = true;
        if(!punctual) temp += str[i];
    }
    str = temp;
}
void Word::toLower(string& str) {
    string temp = "";
    for(int i = 0; i < str.size(); i++) {
        char c = str[i];
        temp += tolower(c);
    }
    str = temp;
}

这里是单词/文档被实例化并添加到向量的地方:

void InvertedFileIndex::parseFile(string fileName) {
    fstream fin, fout;
    fin.open(fileName.c_str(), fstream::in);

    if(fin.is_open()) {
        //Parse input into a single string to the XMLParsing
        xml_document<> doc;
        string str, parse = "";
        while(fin >> str)
                parse += str + " ";
        doc.parse<0>(&parse[0]);
        xml_node<>* root;
        root = doc.first_node("mediawiki");

        //Iterate through each page
        int i = 1;
        for (xml_node<>* page = root->first_node("page"); page; page = page->next_sibling()) {
            Document d;
            Word w;
            string docName = "d" + intToStr(i);
            xml_node<>* title = page->first_node("title");
            d.setTitle(page->first_node("title")->value());
            d.setKey(docName);

            //Find text from document
            xml_node<>* revision = page->first_node("revision");
            xml_node<>* text = revision->first_node("text");
            d.setText(text->value());
            string docText = text->value();

            ////Begin parsing text into words
            stringstream ss(docText); //create a string stream so we can break it into tokens
            string item;
            while (getline(ss, item, ' ')) {
                Word w;
                w.createWord(item);
                w.addDoc(d);
                toks.push_back(w);
            }
            documents.push_back(d);
            writeToIndex();
            i++;
        }
        fin.close();
    }
    else
        cout << "The sample file " << fileName << "could not be opened." << endl;
}

这是输出代码:

void InvertedFileIndex::writeToIndex() {
    fstream fout;
    fout.open("index.txt", fstream::out);

    if(fout.is_open()) {
        for(int i = 0; i < toks.size(); i++) {
            fout << toks[i].getWord() << " = ";
            cout << toks[i].getWord() << " = ";
            for(int j = 0; j < toks[i].getDocs().size(); j++) {
                fout << toks[i].getDocs()[j].d->getKey();
                cout << toks[i].getDocs()[j].d->getKey();
                fout << ", ";
                cout << ", ";
            }
            fout << endl;
            cout << endl;
        }
        fout.close();
    }
    else
        cout << "Index file could not be opened." << endl;
}

【问题讨论】:

  • 其余代码(用于 Word 和输出)会有所帮助。
  • 显然我们需要查看从文件中读取的代码...因为它是错误的。
  • 我已经添加了输入/输出代码和Word类函数实现。这是一个相当奇怪的问题。

标签: c++ file pointers output


【解决方案1】:

在我看来,您正在保存指向超出范围的对象的指针。基本上你的代码是

while (...)
{
    Document d;
    ...
    w.add(d); // add takes a reference and stores pointer to d
}

// sometime later
writeToIndex();

显然,当您开始 writeToIndex 时,您在 while 循环中创建的所有文档对象都已被销毁。所以你有指向不再存在的对象的指针。如果要存储指针,则应在某处动态分配对象。

【讨论】:

  • 是的,这就是我收集到的内容......我尝试在添加指向它的指针后将每个文档添加到向量中,但我猜测向量内部的寻址方式不同。这是一个倒排文件索引的播放代码,所以我会坚持只向文档添加一个键,而不是一个用于定位文档的指针。结构稍后会出现。感谢您的帮助!
  • @TaylorBishop。寻址在任何地方都是一样的。问题是您有一个指向已被破坏的对象的指针。无论指针是否在向量中,都会发生这种情况。这是与指针相关的众多危险之一。拥有一个指针并不能保证所指向的对象是有效的。为了更好地理解这一点,您需要研究对象的生命周期,特别是在堆栈上创建的对象的生命周期与使用 new 在堆上创建的对象的生命周期之间的差异。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-06
相关资源
最近更新 更多