2017-10-30 8 views
0

私はメモリ管理にあまり良くないですし、誰かが私になぜEXC_BAD_ACCESS(コード= 1 ...)エラーが出るのか説明してくれることを願っています。 Xcodeは、getWord()メソッドを呼び出すときにエラーが発生すると報告しています。EXC_BAD_ACCESS、ゲッターを呼び出す

私はトライのデータ構造を実装しています。ノードから単語を取得しようとするとエラーが発生します。私は問題が私のaddまたはaddPhraseメソッドと思うが、何が起こっているのか把握できない。どんな提案も感謝しています。

トライとNodeクラス:

#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); 
      } 
     } 
    } 
}; 

主な - ちょうど最初のノードからの言葉にしようとします。

#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; 
} 
+0

不確定(ニード[MCVE])が、あなたは3件の違反のルールに脆弱です。 [Three of Ruleとは何ですか?](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) – user4581301

+1

この行は疑わしいと思われます。Node root = * new Node(); //なぜインスタンス化しないのですか?Node root;代わりに? – kvr

+0

@kvrは両方の方法を試しましたが、違いはありません。私はちょうどそれを元に戻すことを忘れていた。 – Dez

答えて

0

偶然、Javaの経験はありますか?いずれにしても、C++について注意すべき重要な点がいくつかあります。単純な代入や初期化では、変数を既存のオブジェクトへの参照としてリンクせず、新しいオブジェクトを作成するためにキーワードnewは不要です。

Node current = this->root; 

この行は、addaddPhraseの両方で、あなたのrootノード(子供とすべて)のコピーであるNodeオブジェクトを作成します。したがって、あなたがcurrentに行ったことは、rootに影響しません。 myTrie.root.childrenは(私はそれ以前の問題を逃した場合を除く)、おそらくあなたのクラッシュを引き起こし、まだ空であるためとmainの一番最後に、ライン

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

は無効です。

C++のnewキーワードは、通常の自動保存期間ではなく動的保存期間を持つオブジェクトを作成します。つまり、そのオブジェクトへのポインタにdeleteキーワードを使用しない限り、オブジェクトは何らかの理由で破棄されません。だから、いつでもあなたはnewの、そのオブジェクトからコピーすることによってmyTrieオブジェクトを作成するため

Trie myTrie = *new Trie(); 

プログラムのようなものは、名前のないTrieオブジェクトを作成しませんが、第一の目的は、残りのために存在します「漏れた」とみなされます。リークが多すぎると、悪いフォームのほかに、プログラムが停止するまで元に戻せない方法で、プログラムのコンピュータメモリ使用量が増えます。 Trieオブジェクトをデフォルト・構築するために、それだけで書くことだけで十分です:

addaddPhrase
Trie myTrie; 

は、あなたがいない期間に住んで独立したNodeであることを、あなたのさまざまに関連するcurrentを変数既存のNodeオブジェクトをしたいです関数のこれは実際に生のポインタのためのユースケースである:

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); 
     } 
    } 
} 

current->children.back()current->children[current->children.size()-1]を言うための簡単な方法であることに注意してください。)

関連する問題