使用shared_ptr时出现分段错误 [英] Segmentation fault when using a shared_ptr

查看:137
本文介绍了使用shared_ptr时出现分段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个粒子系统,并且正在为如何构建代码而苦苦挣扎。这个想法是,用户可以创建一个或多个 ParticleEmitter 对象,这些对象通过<$传递给 ParticleManager 对象c $ c> ofxCurlNoise 对象。

I am making a particle system and I'm struggling with how to structure my code. The idea is that a user can create one or several ParticleEmitter objects that are passed to a ParticleManager object via the ofxCurlNoise object.

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

Now, I want that when the user updates the ParticleEmitters objects, the ParticleManager object sees the changes made. So I used shared pointers but I have segmentation faults at different times, whether I use one ParticleEmitter (segmentation fault when the program starts) or a vector<ParticleEmitter> (segmentation fault when the program exits).

这有什么问题?有没有做我想做的设计模式?

What is wrong with this? Is there a design pattern for doing what I'm trying to do?

ofApp.h

#include "ofxCurlNoise.h"

class ofApp : public ofBaseApp{

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

    public:
        void setup();

};

ofApp.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);    

}

ofxCurlNoise.h

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

};

ofxCurlNoise.cpp

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

ParticleManager.h

#include "ParticleEmitter.h"

class ParticleManager{    

    vector<shared_ptr<ParticleEmitter>> emitters;

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

ParticleManager.cpp

#include "ParticleManager.h"

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

void ParticleManager::addEmitter(const shared_ptr<ParticleEmitter>& emitter){
    emitters.push_back(emitter);
}


推荐答案

这不是 std :: shared_ptr 有效。您正在堆栈上创建 ParticleEmitter 的实例,但是 std :: shared_ptr 用于管理创建的实例在堆上。在您的代码中,将新的发射器添加到 ParticleManager 并将其包装到共享指针中时,当 particleEmitters 时,发射器将被破坏向量被销毁(反过来,当您的 ofApp 实例被销毁时)也因此被销毁。

This is not how std::shared_ptr works. You are creating your instances of ParticleEmitter on the stack, but std::shared_ptr is used to manage instances which are created on the heap. In your code, when you add a new emitter to the ParticleManager, and wrap it into a shared pointer, the emitter is destroyed when the particleEmitters vector is destroyed (when, in turn, your ofApp instance is destroyed) and is thus destroyed regardless.

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

When the instance of ofApp is destroyed, both the instance of ofxCurlNoise and particleEmitters are destroyed (in that order). So ofxCurlNoise will in turn destroy the particleManager, which manages your shared pointers, which will then delete your particle emitters (which were originally created on the stack). After all that is done, the particleEmitters vector is getting destroyed, and the runtime system will try to destroy your particle emitters again, leading to the error you are seeing.

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

Furthermore, shared pointers are used to model shared ownership semantics, which I don't see in your use case. I think you'd be better off to either use std::unique_ptr to manage instances created on the heap, or to not use smart pointers at all and create everything on the stack (which you are almost doing already).

这篇关于使用shared_ptr时出现分段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆