why does this crash?

Discussion in 'C++' started by Mr Fish, Oct 10, 2005.

  1. Mr Fish

    Mr Fish Guest

    I don't understand why this crashes in the dtor of Info.

    Can someone explain to me what I'm missing?

    Thanks

    //---------------------------------------------------------
    struct Info
    {
    int* m_pData;

    Info():m_pData(0){}
    Info(int* pData):m_pData(pData)
    {}

    ~Info(){if (m_pData) delete m_pData;}
    };

    class Base
    {
    protected:

    Info m_SomeInfo;

    public:

    virtual ~Base(){}
    };


    class Derived : public Base
    {
    public:

    Derived(){m_SomeInfo = Info(new int(5));}
    };



    int main()
    {
    Derived d;

    return 0;
    }

    //------------------------------------------------------
    Mr Fish, Oct 10, 2005
    #1
    1. Advertising

  2. In class Derived at line:

    m_SomeInfo = Info(new int(5));

    is error. With this, m_SomeInfo.m_pData will point on same location like
    temporary created with Info(new int(5)). So:

    Info(new int(5)).m_pData is same pointer as
    m_SomeInfo.m_pData.

    This will not crach your programm but after destructor is called
    everithing is down. First is called destructor for Info(new int(5)) in
    ctor Derived(), than in main. Both destructors will try to erase same
    memory.

    To prevent this, make operator = in class Info:

    struct Info
    {
    int* m_pData;

    Info():m_pData(0){}
    Info(int* pData):m_pData(pData) {}

    Info& operator=(const Info&) {
    if (this != &Info) { // we do not need self assignment
    // allocate m_pData an copy
    // Info.m_pData in it
    }
    return *this;
    }

    ~Info(){if (m_pData) delete m_pData;}
    };

    Probably, you will need and copy ctor like:

    Info(Info &i) {
    // allocate and copy
    }



    Best,Zaharije Pasalic
    PasalicZaharije, Oct 10, 2005
    #2
    1. Advertising

  3. Mr Fish

    Mr Fish Guest

    Argh! Thankyou! :eek:)


    On Mon, 10 Oct 2005 08:29:57 -0400, "PasalicZaharije"
    <> wrote:

    >In class Derived at line:
    >
    > m_SomeInfo = Info(new int(5));
    >
    >is error. With this, m_SomeInfo.m_pData will point on same location like
    >temporary created with Info(new int(5)). So:
    >
    >Info(new int(5)).m_pData is same pointer as
    >m_SomeInfo.m_pData.
    >
    >This will not crach your programm but after destructor is called
    >everithing is down. First is called destructor for Info(new int(5)) in
    >ctor Derived(), than in main. Both destructors will try to erase same
    >memory.
    >
    >To prevent this, make operator = in class Info:
    >
    >struct Info
    >{
    > int* m_pData;
    >
    > Info():m_pData(0){}
    > Info(int* pData):m_pData(pData) {}
    >
    > Info& operator=(const Info&) {
    > if (this != &Info) { // we do not need self assignment
    > // allocate m_pData an copy
    > // Info.m_pData in it
    > }
    > return *this;
    > }
    >
    > ~Info(){if (m_pData) delete m_pData;}
    >};
    >
    >Probably, you will need and copy ctor like:
    >
    >Info(Info &i) {
    > // allocate and copy
    >}
    >
    >
    >
    >Best,Zaharije Pasalic
    >
    >
    Mr Fish, Oct 10, 2005
    #3
  4. Mr Fish wrote:
    >
    > I don't understand why this crashes in the dtor of Info.
    >
    > Can someone explain to me what I'm missing?


    Rule of three:
    If a class needs a custom destructor, it most likely also needs a
    custom copy constructor and a custom assignment operator.

    Your class Info falls into this category.

    What is going on:
    >
    > Derived(){m_SomeInfo = Info(new int(5));}


    Info( new int(5))

    A single int is generated (with the value 5 in it)



    o------------>+------+
    | 5 |
    +------+

    and a pointer to it is passed in the constructor of the temporary
    Info object. The constructor does:

    > Info(int* pData):m_pData(pData)


    i.e. stores this pointer

    temporary Info object
    +-----------+
    | m_pData |
    | o------------+
    +-----------+ |
    |
    +----------+
    |
    +--->+------+
    | 5 |
    +------+

    What's next? Then comes the assignment in

    m_SomeInfo = Info(new int(5)

    Since you didn't write an assignment operator on your own, the
    compiler generated one for you, which does:

    Info& Info::eek:perator=( const Info& Arg )
    {
    m_pData = Arg.m_pData;
    }

    That is: a memberwise assignment of all members.
    Well in your case, this boils down to:

    temporary Info object
    +-----------+
    | m_pData |
    | o------------+
    +-----------+ |
    |
    +----------+
    |
    +--->+------+
    +--->| 5 |
    | +------+
    |
    +--------------+
    |
    Derived |
    +---------------------+ |
    | | |
    | Base | |
    | +----------------+ | |
    | | m_SomeInfo | | |
    | | +------------+ | | |
    | | | m_pData | | | |
    | | | o---------------+
    | | +------------+ | |
    | +----------------+ |
    +---------------------+

    That is: The m_pData pointer in m_SomeInfo inside Base points
    to the same int as the temporary Info object does.

    Well. A few nanoseconds later, the temporary info object ceases to
    exist. It's destructor is called, which does:

    ~Info(){if (m_pData) delete m_pData;}

    (The if is not necessary. You can safey delete a 0 pointer).
    Thus the temporary object deletes the int it has allocted just
    before itself gets wiped out of memory. This leaves you with:

    +--->
    |
    |
    +--------------+
    |
    Derived |
    +---------------------+ |
    | | |
    | Base | |
    | +----------------+ | |
    | | m_SomeInfo | | |
    | | +------------+ | | |
    | | | m_pData | | | |
    | | | o---------------+
    | | +------------+ | |
    | +----------------+ |
    +---------------------+


    Ooops. The pointer m_pData in m_SomeInfo now points to nowhere
    in memory. So when finaly that Derived object gets destroyed, all
    destructors are run, especially the dtor of m_SomeInfo which tries
    to delete .... hmm ... nothing sensible. There is no data anymore
    where the pointer is pointing to. -> Claboom.

    Google for 'Rule of three C++'
    and should find enough references on how to cure this thing.

    --
    Karl Heinz Buchegger
    Karl Heinz Buchegger, Oct 10, 2005
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alf P. Steinbach

    Re: Why does this crash?

    Alf P. Steinbach, Jul 18, 2003, in forum: C++
    Replies:
    5
    Views:
    361
  2. Developwebsites

    why does it crash?

    Developwebsites, Oct 10, 2003, in forum: C++
    Replies:
    6
    Views:
    351
    Jerry Coffin
    Oct 11, 2003
  3. Mr. SweatyFinger

    why why why why why

    Mr. SweatyFinger, Nov 28, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    853
    Mark Rae
    Dec 21, 2006
  4. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,739
    Smokey Grindel
    Dec 2, 2006
  5. Phi!
    Replies:
    1
    Views:
    168
Loading...

Share This Page