"No matching enumerant" on member of a duplicated instance as the copied instance has been deleted
-
Hello,
I have a problem when I try to duplicate an instance when the original instance as been deleted.
It cause the crash of my program, please see the image below.I don't know if I'm doing right trying a deep copy of each elements.
It's a lot of code, if you have the courage to help me it would be great, I'm really stuck...
I made BREAKPOINT comments showing what is the state of the data shown by debugger at two moments :- at the Delete Fx action
- at the Select track action we want to duplicate
To explain the data stored :
Cue >
------listOf(CueTrack*) >
------------------------AnimationsSubTrack* >
-------------------------------------------- listOf(Animation*)
------------------------listOf(FxSubTrack*)
------------------------ZoneChaseSubTrack *AnimationsSubTrack, FxSubTrack and ZoneChaseSubTrack are derived from CueAbstractSubTrack
a CueAbstractSubTrack as an enum member _typeHere is my code :
CueTrack :
class CueTrack : public QObject { Q_OBJECT public: CueTrack(); CueTrack(const CueTrack &other); CueTrack & operator=(const CueTrack&other); ~CueTrack(); [...] protected: AnimationsSubTrack *_animationsList; QVector<FxSubTrack*> _fxList; ZoneChaseSubTrack *_zoneChase; }; CueTrack::CueTrack() { _animationsList = new AnimationsSubTrack(); _zoneChase = nullptr; } CueTrack::CueTrack(const CueTrack &other) { *this = other; } CueTrack &CueTrack::operator=(const CueTrack &other) { if(&other == this) return *this; if(other._animationsList) _animationsList = new AnimationsSubTrack(*other._animationsList); else _animationsList = nullptr; while(!_fxList.isEmpty()) { FxSubTrack *f = _fxList.takeLast(); if(f) f->deleteLater(); } _fxList.clear(); _fxList = QVector<FxSubTrack *>(other._fxList); _fxList.detach(); if(other._zoneChase) _zoneChase = new ZoneChaseSubTrack(*other._zoneChase); else _zoneChase = nullptr; return *this; } CueTrack::~CueTrack() { if(_animationsList) _animationsList->deleteLater(); while(!_fxList.isEmpty()) { FxSubTrack *f = _fxList.takeLast(); if(f) f->deleteLater(); } _fxList.clear(); if(_zoneChase) _zoneChase->deleteLater(); }
class FxSubTrack : public CueAbstractSubTrack { Q_OBJECT public: FxSubTrack(); virtual ~FxSubTrack(); FxSubTrack(const FxSubTrack & other); virtual FxSubTrack &operator=(const FxSubTrack & other); [...] }; FxSubTrack::FxSubTrack():CueAbstractSubTrack() { _type = CueSubTrack_Type::Fx; } FxSubTrack::~FxSubTrack() { } FxSubTrack::FxSubTrack(const FxSubTrack &other) { *this = other; } FxSubTrack &FxSubTrack::operator=(const FxSubTrack &other) { if(&other == this) return *this; _isNull = other._isNull; _type = CueSubTrack_Type::Fx; return *this; }
AnimationsSubTrack
class AnimationsSubTrack : public CueAbstractSubTrack { Q_OBJECT public: AnimationsSubTrack(); ~AnimationsSubTrack(); AnimationsSubTrack(const AnimationsSubTrack & other); virtual AnimationsSubTrack &operator=(const AnimationsSubTrack & other); void clear(); [...] private: QVector<Animation*> _animationList; }; AnimationsSubTrack::AnimationsSubTrack():CueAbstractSubTrack() { _type = CueSubTrack_Type::Animations; } AnimationsSubTrack::~AnimationsSubTrack() { clear(); } AnimationsSubTrack::AnimationsSubTrack(const AnimationsSubTrack &other) { *this = other; } AnimationsSubTrack &AnimationsSubTrack::operator=(const AnimationsSubTrack &other) { if(&other == this) return *this; _isNull = other._isNull; _type = CueSubTrack_Type::Animations; clear(); _animationList = QVector<Animation *>(other._animationList); _animationList.detach(); return *this; } void AnimationsSubTrack::clear() { while(!_animationList.isEmpty()) { Animation *a = _animationList.takeLast(); if(a) a->deleteLater(); } _animationList.clear(); }
CueAbstractSubTrack
enum class CueSubTrack_Type { Undefined, Animations, Fx, ZoneChase }; class CueAbstractSubTrack : public QObject { Q_OBJECT public: CueAbstractSubTrack(); CueAbstractSubTrack(const CueAbstractSubTrack & other); virtual CueAbstractSubTrack &operator=(const CueAbstractSubTrack & other); CueSubTrack_Type virtual getSubTrackType() = 0; bool virtual isNull() {return true;} protected: CueSubTrack_Type _type; bool _isNull = true; }; CueAbstractSubTrack::CueAbstractSubTrack() { _type = CueSubTrack_Type::Undefined; } CueAbstractSubTrack::CueAbstractSubTrack(const CueAbstractSubTrack &other) { *this = other; } CueAbstractSubTrack &CueAbstractSubTrack::operator=(const CueAbstractSubTrack &other) { _isNull = other._isNull; _type = other._type; return *this; }
EditCueTimelineWidget
class EditCueTimelineWidget : public QWidget { [...] private slots: void duplicateCurrentTrack(); void addFxToCurrentTrack(FxSubTrack * fxData = nullptr, CueTrack *trackData_source = nullptr); void removeSubFromCurrentTrack(); [...] private: Cue* _cue; [...] }; EditCueTimelineWidget::EditCueTimelineWidget(QWidget *parent) : QWidget(parent), ui(new Ui::EditCueTimelineWidget) { [...] connect(ui->duplicateTrackButton, SIGNAL(released()), this, SLOT(duplicateCurrentTrack())); connect(ui->addFxButton, SIGNAL(released()), this, SLOT(addFxToCurrentTrack())); connect(ui->removeSubButton, SIGNAL(released()), this, SLOT(removeSubFromCurrentTrack())); } void EditCueTimelineWidget::addFxToCurrentTrack(FxSubTrack * fxData, CueTrack *trackData_source) { if(_cue == nullptr) return; TrackLabel * activeTrack; if(fxData != nullptr) { if(trackData_source == nullptr) return; activeTrack = findTrackLabelFromTrackData(trackData_source); if(activeTrack == nullptr) return; } else { activeTrack = getActiveTrack(); if(activeTrack == nullptr) return; fxData = new FxSubTrack(); activeTrack->getTrackData()->appendFx(fxData); } SubTrackLabel * subLabel = new SubTrackLabel(activeTrack,fxData); activeTrack->_subTrackLabelList.insert(1,subLabel); [...] } void EditCueTimelineWidget::duplicateCurrentTrack() { if(_cue == nullptr) return; TrackLabel * activeTrack = getActiveTrack(); if(activeTrack == nullptr || activeTrack->getTrackData() == nullptr) return; CueTrack *trackData = new CueTrack(*activeTrack->getTrackData()); _cue->appendTrack(trackData); TrackLabel * l = new TrackLabel(ui->TimelineEditScrollArea,trackData); _trackLabelList.append(l); ui->scrollAreaWidgetContents->layout()->addWidget(l); [...] setAnimationsSubTrack(trackData->animationList(),trackData); QVectorIterator<FxSubTrack*> itFx(trackData->fxList()); while (itFx.hasNext()) { auto fx = itFx.next(); addFxToCurrentTrack(fx,trackData); } [...] } void EditCueTimelineWidget::removeSubFromCurrentTrack() { if(_cue == nullptr) return; TrackLabel * activeTrack = getActiveTrack(); if(activeTrack == nullptr) return; CueTrack * trackData = activeTrack->getTrackData(); if(trackData == nullptr) return; SubTrackLabel * activeSub = activeTrack->getActiveSub(); if(activeSub == nullptr) return; [...] for (int k = 0; k < activeTrack->_subTrackLabelList.size(); k++) { if( activeTrack->_subTrackLabelList.at(k) == activeSub) { SubTrackLabel *subRemovable = activeTrack->_subTrackLabelList.takeAt(k); if(activeSub->getType() == CueSubTrack_Type::Fx) trackData->removeFx(qobject_cast<FxSubTrack*>(activeSub->getSubTrackData())); else trackData->deleteZoneChase(); subRemovable->deleteLater(); break; } } /* BREAKPOINT action 1. at the Delete Fx action * *this * -----*_cue * ----------_cueTrackList <2 elements> * -------------------------[0] * ------------------------------*animationList @0x13...bf0 * ----------------------------------------------_type Animation * ------------------------------_fxList <0 element> * -------------------------[1] * ------------------------------*animationList @0x13...1f0 * ----------------------------------------------_type Animation * ------------------------------_fxList <1 element> * ----------------------------------------------[0] * -----------------------------------------------------_type Fx */ [...] } void EditCueTimelineWidget::newActivatedReceived() { // Slot called whenever a track or subTrack is selected refreshModifButtonsState(); /* BREAKPOINT 2. at the Select track action we want to duplicate * *this * -----*_cue * ----------_cueTrackList <2 elements> * -------------------------[0] * ------------------------------*animationList @0x13...bf0 * ----------------------------------------------_type Animation * ------------------------------_fxList <0 element> * -------------------------[1] * ------------------------------*animationList @0x13...1f0 * ----------------------------------------------_type Animation * ------------------------------_fxList <1 element> * ----------------------------------------------[0] * -----------------------------------------------------_type 0n670234544 (No matching enumerant) */ }
I don't know what happened between the end of the delete a subTrack slot and the Selected track slot... but I have this _type beeing 0n670234544 (No matching enumerant)
Any idea ?
-
@SGaist
Hey thank you,
I removed the QObject heredity for every class since I don't need ^^
I made every copy constructor and operator= overload not usable (= delete)
I made for each a static clone() method which makes a deep copyCueTrack * CueTrack::clone(CueTrack *other) { if(!other) return nullptr; CueTrack * trackToReturn = new CueTrack(); if(other->_animationsList) { delete trackToReturn->_animationsList; trackToReturn->_animationsList = AnimationsSubTrack::clone(other->_animationsList); } QVectorIterator<FxSubTrack*> it(other->_fxList); while (it.hasNext()) { auto p = it.next(); FxSubTrack * fx = FxSubTrack::clone(p); trackToReturn->appendFx(fx); } if(other->_zoneChase) trackToReturn->_zoneChase = ZoneChaseSubTrack::clone(other->_zoneChase); return trackToReturn; }
-
Hi,
The first thing to fix: QObject is not copyable. If you really want to create a copy of an object, then write a "clone" method that will create a new object and set all its properties to match the one you are cloning from.
-
@SGaist
Hey thank you,
I removed the QObject heredity for every class since I don't need ^^
I made every copy constructor and operator= overload not usable (= delete)
I made for each a static clone() method which makes a deep copyCueTrack * CueTrack::clone(CueTrack *other) { if(!other) return nullptr; CueTrack * trackToReturn = new CueTrack(); if(other->_animationsList) { delete trackToReturn->_animationsList; trackToReturn->_animationsList = AnimationsSubTrack::clone(other->_animationsList); } QVectorIterator<FxSubTrack*> it(other->_fxList); while (it.hasNext()) { auto p = it.next(); FxSubTrack * fx = FxSubTrack::clone(p); trackToReturn->appendFx(fx); } if(other->_zoneChase) trackToReturn->_zoneChase = ZoneChaseSubTrack::clone(other->_zoneChase); return trackToReturn; }
-