Search code examples
c++qtpointersstackcorruption

Stack corruption with copying a QMap containing a base class pointer in C++


I have the following setting:

class A {
  public:
  A();
  virtual ~A();
  A(const A&other) {*this = other;}
  A& operator=(const A&) {/*assigne reference members, create new of pointer members*/}

  /* some other stuff */
}

class B : public A {
  public:
  B();
  virtual ~B();
  B(const B&other) {*this = other;}
  B& operator=(const B&rhs) { A::operator=(rhs); /*assigne reference members, create new of pointer members*/}

  /* some other stuff */
}

class C : public A {
  public:
  C();
  virtual ~C();
  C(const C&other) {*this = other;}
  C& operator=(const C&) { A::operator=(rhs); /*assigne reference members, create new of pointer members*/}

  /* some other stuff */
}


class D {
  public:
  D();
  virtual ~D();
  D(const D&other) {*this = other;}
  D& operator=(const D&rhs) {
    /* iterate through map and create new instances of B or C */
    m_list = rhs.m_list;
  }

  QMap<QUuid, A*> GetMap() {return m_map;}
  QList<QUuid> GetList {return m_list;}

  private:
  QMap<QUuid, A*> m_map;
  QList<QUuid> m_list;

  /* some other stuff */
}

Now I put some B and C into the map get a reference from D which creates a deep copy of the QMap through D's copy constructor. If I try to get the size of the QMap it is working but the list is corrupted. With help of the debugger I figured out that the QList in D gets corrupted when the assignment operator of the QMap calls std::swap. It is completely unclear for me what happens there with my memory.

Has this something to do with the derivation and using the base class pointer? If I change the QMap to std::map my program also crashes but at another point with another problem.

Thanks for any advices and hints.


Solution

  • Now I put some B and C into the map get a reference from D which creates a deep copy of the QMap through D's copy constructor.

    The map is copied but you then have two maps pointing to the same objects, the question is then who owns the objects.

    It would be better that you instead of storing raw pointers use shared_ptr to your instances

    QMap<QUuid, std::shared_ptr<A>> m_map;

    Also note that your method GetMap() returns a copy of the map, not the actual map so when you call that you have one more map that maps to the same objects.