2017-10-30 22 views
0

저는 메모리 관리에별로 좋지 않습니다. 누군가 내가 왜 EXC_BAD_ACCESS (코드 = 1 ...) 오류가 발생하는지 설명 할 수 있기를 바랍니다. Xcode는 getWord() 메서드를 호출 할 때 오류가 발생한다고 말합니다.EXC_BAD_ACCESS, getter를 호출하십시오.

트라이 데이터 구조를 구현할 때 노드에서 단어를 가져 오려고하면 오류가 발생합니다. 내 문제는 내 add 또는 addPhrase 메서드로 생각하지만 무슨 일이 일어나고 있는지 파악할 수 없다. 모든 제안을 부탁드립니다.

트리는 및 노드 클래스 :

#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])하지만 당신은 세 가지 위반 규칙에 취약하다. [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은 새 객체를 만드는 데 필요하지 않습니다. addaddPhrase 모두

Node current = this->root; 

이 줄

은, 당신의 root 노드 (어린이와 모든)의 복사 Node 개체를 만듭니다. 그래서 당신이 current에 할 일은 root에 영향을 미치지 않습니다. 그리고 main의 맨 끝, myTrie.root.children (나는 이전 문제를 놓친하지 않는 한) 가능성이 귀하의 충돌을 일으키는 원인이 여전히 비어 있기 때문에

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]을 말하는 짧은 방법입니다 참고.)