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
指向错误的地址。另外,当向量超出作用域元素时