Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用共享ptr时出现分段错误_C++_C++11_Design Patterns_Overloading_Shared Ptr - Fatal编程技术网

C++ 使用共享ptr时出现分段错误

C++ 使用共享ptr时出现分段错误,c++,c++11,design-patterns,overloading,shared-ptr,C++,C++11,Design Patterns,Overloading,Shared Ptr,我正在制作一个粒子系统,我正在努力研究如何构造我的代码。用户可以创建一个或多个particlemitter对象,这些对象通过xcurlnise对象传递给ParticleManager对象 现在,我希望当用户更新particlemitters对象时,ParticleManager对象可以看到所做的更改。所以我使用了共享指针,但我在不同的时间有分段错误,无论是使用一个particlemitter(程序启动时分段错误)还是向量(程序退出时分段错误) 这有什么问题?有没有一个设计模式来完成我想做的事情

我正在制作一个粒子系统,我正在努力研究如何构造我的代码。用户可以创建一个或多个
particlemitter
对象,这些对象通过xcurlnise对象传递给
ParticleManager
对象

现在,我希望当用户更新
particlemitters
对象时,
ParticleManager
对象可以看到所做的更改。所以我使用了共享指针,但我在不同的时间有分段错误,无论是使用一个
particlemitter
(程序启动时分段错误)还是
向量(程序退出时分段错误)

这有什么问题?有没有一个设计模式来完成我想做的事情

ofApp.h

#include "ofxCurlNoise.h"

class ofApp : public ofBaseApp{

    // ParticleEmitter particleEmitter;
    vector<ParticleEmitter> particleEmitters;
    ofxCurlNoise curlNoise;

    public:
        void setup();

};
#include "ParticleManager.h"

class ofxCurlNoise {    

    ParticleManager particleManager;

    public:
        void setup(ParticleEmitter& emitter, int n);
        void setup(vector<ParticleEmitter>& emitters, int n);

    private:
        void setup(int n);    

};
#include "ParticleEmitter.h"

class ParticleManager{    

    vector<shared_ptr<ParticleEmitter>> emitters;

    public:
        void addEmitter(const shared_ptr<ParticleEmitter>& emitter);
        void setup(int n);
};
xcurlnise.h的

#include "ofxCurlNoise.h"

class ofApp : public ofBaseApp{

    // ParticleEmitter particleEmitter;
    vector<ParticleEmitter> particleEmitters;
    ofxCurlNoise curlNoise;

    public:
        void setup();

};
#include "ParticleManager.h"

class ofxCurlNoise {    

    ParticleManager particleManager;

    public:
        void setup(ParticleEmitter& emitter, int n);
        void setup(vector<ParticleEmitter>& emitters, int n);

    private:
        void setup(int n);    

};
#include "ParticleEmitter.h"

class ParticleManager{    

    vector<shared_ptr<ParticleEmitter>> emitters;

    public:
        void addEmitter(const shared_ptr<ParticleEmitter>& emitter);
        void setup(int n);
};
#包括“ParticleManager.h”
XcurlNoise{
ParticleManager ParticleManager;
公众:
无效设置(粒子发射器和发射器,int n);
无效设置(矢量和发射器,int n);
私人:
无效设置(int n);
};
xcurlnise.cpp的

#include "ofApp.h"

void ofApp::setup(){
    // This produces a segfault as soon as the program starts
    // particleEmitter.setup();
    // curlNoise.setup(particleEmitter, 1024*256);

    // This produces a segfault when the program exits
    ParticleEmitter emitter;
    emitter.setup();
    particleEmitters.push_back(emitter);
    curlNoise.setup(particleEmitters, 1024*256);    

}
#include "ofxCurlNoise.h"

void ofxCurlNoise::setup(ParticleEmitter& emitter, int n){
    particleManager.addEmitter(shared_ptr<ParticleEmitter>(&emitter));
    setup(n);
}

void ofxCurlNoise::setup(vector<ParticleEmitter>& emitters, int n){
    for(auto& e : emitters){
        particleManager.addEmitter(shared_ptr<ParticleEmitter>(&e));
    }
    setup(n);
}

void ofxCurlNoise::setup(int n){
    particleManager.setup(n);
}
#include "ParticleManager.h"

void ParticleManager::setup(int n){
    //...
}

void ParticleManager::addEmitter(const shared_ptr<ParticleEmitter>& emitter){
    emitters.push_back(emitter);
}
#包括“ofxcurlnise.h”
无效XcurlNoise::设置(ParticleEmitter和emitter,int n){
particleManager.addEmitter(共享_ptr(&emitter));
设置(n);
}
设置无效(向量和发射器,int n){
用于(自动和电气:发射器){
分词管理器.加法器(共享);
}
设置(n);
}
无效的XcurlNoise::设置(int n){
粒子管理器设置(n);
}
ParticleManager.h

#include "ofxCurlNoise.h"

class ofApp : public ofBaseApp{

    // ParticleEmitter particleEmitter;
    vector<ParticleEmitter> particleEmitters;
    ofxCurlNoise curlNoise;

    public:
        void setup();

};
#include "ParticleManager.h"

class ofxCurlNoise {    

    ParticleManager particleManager;

    public:
        void setup(ParticleEmitter& emitter, int n);
        void setup(vector<ParticleEmitter>& emitters, int n);

    private:
        void setup(int n);    

};
#include "ParticleEmitter.h"

class ParticleManager{    

    vector<shared_ptr<ParticleEmitter>> emitters;

    public:
        void addEmitter(const shared_ptr<ParticleEmitter>& emitter);
        void setup(int n);
};
#包括“ParticleEmitter.h”
类分词管理器{
矢量发射器;
公众:
无效加法器(常数共享检测器和发射器);
无效设置(int n);
};
ParticleManager.cpp

#include "ofApp.h"

void ofApp::setup(){
    // This produces a segfault as soon as the program starts
    // particleEmitter.setup();
    // curlNoise.setup(particleEmitter, 1024*256);

    // This produces a segfault when the program exits
    ParticleEmitter emitter;
    emitter.setup();
    particleEmitters.push_back(emitter);
    curlNoise.setup(particleEmitters, 1024*256);    

}
#include "ofxCurlNoise.h"

void ofxCurlNoise::setup(ParticleEmitter& emitter, int n){
    particleManager.addEmitter(shared_ptr<ParticleEmitter>(&emitter));
    setup(n);
}

void ofxCurlNoise::setup(vector<ParticleEmitter>& emitters, int n){
    for(auto& e : emitters){
        particleManager.addEmitter(shared_ptr<ParticleEmitter>(&e));
    }
    setup(n);
}

void ofxCurlNoise::setup(int n){
    particleManager.setup(n);
}
#include "ParticleManager.h"

void ParticleManager::setup(int n){
    //...
}

void ParticleManager::addEmitter(const shared_ptr<ParticleEmitter>& emitter){
    emitters.push_back(emitter);
}
#包括“ParticleManager.h”
void ParticleManager::设置(int n){
//...
}
无效粒子管理器::加法器(常量共享_ptr和发射器){
发射器。推回(发射器);
}

这不是
std::shared\u ptr
的工作方式。您正在堆栈上创建
ParticleEmitter
的实例,但
std::shared_ptr
用于管理在堆上创建的实例。在代码中,当您向
ParticleManager
添加一个新的发射器,并将其包装到一个共享指针中时,当
particleEmitters
向量被销毁时(反过来,当您的
ofApp
实例被销毁时),发射器将被销毁,因此无论如何都将被销毁

当销毁
ofApp
的实例时,xcurlnise
实例和
particlemitters
实例都将销毁(按该顺序)。因此,ofxCurlNoise将依次破坏管理共享指针的
粒子管理器
,然后删除粒子发射器(最初在堆栈上创建)。完成所有这些操作后,
粒子发射器
向量将被销毁,运行时系统将再次尝试销毁粒子发射器,从而导致您看到的错误


此外,共享指针用于对共享所有权语义建模,这在您的用例中没有看到。我认为您最好使用
std::unique_ptr
来管理在堆上创建的实例,或者根本不使用智能指针并在堆栈上创建所有内容(您几乎已经这样做了)。

这不是
std::shared_ptr
的工作方式。您正在堆栈上创建
ParticleEmitter
的实例,但
std::shared_ptr
用于管理在堆上创建的实例。在代码中,当您向
ParticleManager
添加一个新的发射器,并将其包装到一个共享指针中时,当
particleEmitters
向量被销毁时(反过来,当您的
ofApp
实例被销毁时),发射器将被销毁,因此无论如何都将被销毁

当销毁
ofApp
的实例时,xcurlnise
实例和
particlemitters
实例都将销毁(按该顺序)。因此,ofxCurlNoise将依次破坏管理共享指针的
粒子管理器
,然后删除粒子发射器(最初在堆栈上创建)。完成所有这些操作后,
粒子发射器
向量将被销毁,运行时系统将再次尝试销毁粒子发射器,从而导致您看到的错误


此外,共享指针用于对共享所有权语义建模,这在您的用例中没有看到。我认为您最好使用
std::unique_ptr
来管理在堆上创建的实例,或者根本不使用智能指针并在堆栈上创建所有内容(您几乎已经在这样做了)。

您永远不应该像这里这样从普通指针创建共享_ptr:

 shared_ptr<ParticleEmitter>(&e)
shared_ptr&e)

这将尝试释放particleMitter两次。一旦包含ParticleEmitter对象的向量超出范围,一旦共享\u ptr超出范围。

您不应该像这里这样从普通指针创建共享\u ptr:

 shared_ptr<ParticleEmitter>(&e)
void ofxCurlNoise::setup(vector<ParticleEmitter>& emitters, int n){
   for(auto& e : emitters){
    particleManager.addEmitter(shared_ptr<ParticleEmitter>(&e));
  }
  setup(n);
}
shared_ptr&e)
这将尝试释放particleMitter两次。一次是因为包含ParticleEmitter对象的向量超出范围,一次是因为共享的ptr超出范围。

void of xcurlnise::setup(向量和发射器,int n){
void ofxCurlNoise::setup(vector<ParticleEmitter>& emitters, int n){
   for(auto& e : emitters){
    particleManager.addEmitter(shared_ptr<ParticleEmitter>(&e));
  }
  setup(n);
}
用于(自动和电气:发射器){ 分词管理器.加法器(共享); } 设置(n); }
看起来您正在从“堆栈”分配的对象生成共享指针。您应该使用
new
make_shared
来构造
particlemitter
对象,但当向量大小调整且
particlemitter
复制到新位置时,
shared_ptr
指向错误的地址。另外,当向量超出作用域元素时