"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 ?
-
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; } -
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 ?
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.
-
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; } -
A Amir Hammoutene has marked this topic as solved on