EXC_BAD_ACCESS,调用getter

时间:2017-10-30 23:27:33

标签: c++ c++11 memory exc-bad-access trie

我对内存管理不太满意,我希望有人可以帮我解释为什么我收到EXC_BAD_ACCESS(code = 1 ...)错误。 Xcode表示调用getWord()方法时会发生错误。

我正在实现一个trie数据结构,当我尝试从我的节点获取一个单词时会发生错误。我认为问题出在我的add或addPhrase方法上,但我无法弄清楚最新情况。任何建议都表示赞赏。

Trie和Node Class:

private boolean prepareMediaRecorder() {
    mediaRecorder = new MediaRecorder();
    mCamera.unlock();
    mediaRecorder.setCamera(mCamera);
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
    mediaRecorder.setProfile(CamcorderProfile.get(camId, CamcorderProfile.QUALITY_TIME_LAPSE_HIGH));
    mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_WB);
    mediaRecorder.setMaxDuration(30000); //set maximum duration 60 sec.
    mediaRecorder.setMaxFileSize(50000000); //set maximum file size 50M
    mediaRecorder.setPreviewDisplay(new Surface(mTextureView.getSurfaceTexture()));
    mediaRecorder.setOutputFile(Environment.getExternalStorageDirectory() + "/tempVid.mp4");



    if(camId == Camera.CameraInfo.CAMERA_FACING_BACK){
        mediaRecorder.setOrientationHint(90);
    }else{
        mediaRecorder.setOrientationHint(270);
    }
    try {
        mediaRecorder.prepare();
    } catch (IllegalStateException e) {
        e.printStackTrace();
        releaseMediaRecorder();
        return false;
    } catch (IOException e) {
        releaseMediaRecorder();
        return false;
    }
    return true;
}

Main - 只是尝试从第一个节点开始的单词。

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

1 个答案:

答案 0 :(得分:0)

您是否有过Java经验?在任何情况下,有一些关于C ++的重要注意事项:简单的赋值或初始化不会将变量链接为对现有对象的引用,并且创建新对象不需要关键字new

Node current = this->root;

addaddPhrase中的这一行创建了一个Node对象,它是root节点(子节点和所有节点)的副本。因此,您对current所做的任何操作都不会影响root。在main的最后,行

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

无效,因为myTrie.root.children仍为空,可能导致您的崩溃(除非我错过了之前的问题)。

C ++中的new关键字创建一个具有动态存储持续时间而不是通常的自动存储持续时间的对象,这意味着除非您使用delete关键字,否则不会因任何原因销毁该对象指向该对象的指针。所以每次你做

之类的事情
Trie myTrie = *new Trie();

由于Trie,程序创建一个没有名称的new对象,然后通过从该对象复制来创建myTrie对象,但第一个对象将存在于其余的该计划被视为“泄露”。除了形式不好之外,太多的泄漏会以一种在程序停止之前无法逆转的方式增加程序对计算机内存的使用。要默认构造一个Trie对象,只需编写:

即可
Trie myTrie;

addaddPhrase中,您希望变量current与不同的现有Node对象相关联,而不是独立的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]。)