简体   繁体   English

EXC_BAD_ACCESS,调用getter

[英]EXC_BAD_ACCESS, calling getter

I'm not very good with memory management and I'm hoping someone can help explain to me why I am getting the EXC_BAD_ACCESS (code=1...) error. 我对内存管理不是很好,我希望有人可以帮助我解释为什么我遇到EXC_BAD_ACCESS(code = 1 ...)错误。 Xcode says that the error occurs when calling the getWord() method. Xcode表示在调用getWord()方法时发生错误。

I am implementing a trie data structure and the error occurs when I try to get a word from my node. 我正在实现一个trie数据结构,当我尝试从节点中获取一个单词时发生错误。 I think the problem is with my add or addPhrase method but I cant figure out whats going on. 我认为问题出在我的add或addPhrase方法上,但我不知道发生了什么。 Any suggestions are appreciated. 任何建议表示赞赏。

Trie and Node Class: 特里和节点类:

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <sstream>


using namespace std;


class Node
{
private:
    string word;
    bool endOfSentence = false;
    int weight = -1;


public:

    vector<Node> children = {};

    Node() {
        this->setWord("");
    }

    Node(string s){
        this->setWord(s);
    }

    string getWord(){
        return this->word;
    }
    /*vector<Node> getChildren() {   //children private
        return this->children;
    }*/
    void setWord(string s) {
        this->word = s;
    }

    void setEOS(){
        this->endOfSentence = true;
    }

    void setWeight(int weight){
        this->weight = weight;
    }
};


class Trie
{
public:
    Node root = *new Node();

    string get(string p) {
        string s = "stub";
        return s;
    }

    void add(vector<string> phrase, int weight){
        Node current = this->root;
        vector<string> sentence = phrase;
        int w = weight;
        int found = -1;

        for (int i = 0; i < current.children.size(); i++) {
            if (phrase[0] == current.children[i].getWord()) {
                found = i;
            }
        }
        if (found >= 0) {
            current = current.children[found];
            sentence.erase(sentence.begin());
            add(sentence,w);
        }
        else {
            addPhrase(sentence,w);
        }
    }

    void addPhrase(vector<string> phrase, int weight) {
        Node current = this->root;
        for (int i = 0; i < phrase.size(); i++) {
            Node temp = *new Node(phrase[i]);
            current.children.push_back(temp);
            current = current.children[current.children.size() - 1];
            if (i == phrase.size() - 1) {
                current.setEOS();
                current.setWeight(weight);
            }
        }
    }
};

Main - just attempts to the the word from the first node. Main-仅尝试从第一个节点输入单词。

#include "Trie.cpp"
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

int main(int argc, char* argv[]) {
    // Initialize trie up here
    Trie myTrie = *new Trie();

    // parse input lines until I find newline
    for(string line; getline(cin, line) && line.compare(""); ) {
        stringstream ss(line);
        string string_weight;
        ss >> string_weight;
        int weight = stoi(string_weight);

        // I am just going to put these words into a vector
        // you probably want to put them in your trie

        vector<string> phrase = {};
        for(string word; ss >> word;) {
            phrase.push_back(word);
        }


        myTrie.add(phrase, weight);


    }
    // parse query line
    string query;
    getline(cin, query);

    cout << myTrie.root.children[0].getWord() << endl;



    return 0;
}

Do you have some experience with Java, by chance? 您是否有使用Java的经验? In any case, there are a couple of important things to note about C++: a simple assignment or initialization does not link a variable as a reference to an existing object, and the keyword new is not needed to create new objects. 无论如何,关于C ++有几件重要的事情要注意:简单的赋值或初始化不会将变量链接为对现有对象的引用,并且不需要关键字new来创建新对象。

Node current = this->root;

This line, in both add and addPhrase , creates a Node object which is a copy of your root node (children and all). 这条线,在这两个addaddPhrase ,创建一个Node对象,它是你的副本root节点(孩子和所有)。 So anything you do to current won't affect root . 因此,您对current所做的任何操作都不会影响root And at the very end of main , the line main最后,

cout << myTrie.root.children[0].getWord() << endl;

is invalid because myTrie.root.children is still empty, possibly causing your crash (unless I missed an earlier problem). 无效,因为myTrie.root.children仍然为空,可能会导致崩溃(除非我错过了先前的问题)。

The new keyword in C++ creates an object with dynamic storage duration instead of the usual automatic storage duration, which means that the object will not be destroyed for any reason unless you use the delete keyword on a pointer to that object. C ++中的new关键字创建一个具有动态存储持续时间而不是通常的自动存储持续时间的对象,这意味着该对象不会由于任何原因被破坏,除非您在指向该对象的指针上使用delete关键字。 So any time you do something like 所以任何时候你做类似的事情

Trie myTrie = *new Trie();

the program creates a Trie object without a name because of the new , then creates the myTrie object by copying from that object, but the first object will exist for the rest of the program and is considered "leaked". 该程序会创建一个没有名字的Trie对象,因为它是new ,然后通过从该对象复制而创建myTrie对象,但是第一个对象将在程序的其余部分存在,并被视为“泄漏”。 Too many leaks, besides being bad form, will increase your program's usage of computer memory in a way that can't be reversed until the program stops. 除了形式不正确外,还有太多的泄漏,这将增加程序对计算机内存的使用,而这种方式在程序停止之前是无法逆转的。 To default-construct a Trie object, it's enough to just write: 要默认构造一个Trie对象,只需编写即可:

Trie myTrie;

In add and addPhrase , you want your variable current to relate to different existing Node objects, not to be an independent Node that lives for the duration of the function. addaddPhrase ,您希望变量current与不同的现有Node对象相关,而不是成为在功能持续时间addPhrase在的独立Node This is actually a use case for a raw pointer: 这实际上是原始指针的用例:

void addPhrase(vector<string> phrase, int weight) {
    Node* current = &this->root;
    for (int i = 0; i < phrase.size(); i++) {
        Node temp(phrase[i]);
        current->children.push_back(temp);
        current = &current->children.back();
        if (i == phrase.size() - 1) {
            current->setEOS();
            current->setWeight(weight);
        }
    }
}

(Note current->children.back() is a shorter way of saying current->children[current->children.size()-1] .) (请注意current->children.back()是说current->children[current->children.size()-1]一种简短方法。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM