Re: Destructors can copying objects

Discussion in 'C++' started by Yannick Tremblay, Apr 4, 2011.

  1. On 2011-04-02, Ruben Safir <> wrote:
    >
    > I am creating a linked link program which created a segmentation fault
    > and a core at the end of the program. The program is trying to delete an
    > already deleted object, and I can't seem to protect my program from
    > this. I fixed the problem by sending an object to a function by
    > reference rather than by value, but I'm not satisfied with the solution.
    >
    > The list has node objects
    >
    > namespace chainlist {
    >
    >
    > /*
    > *
    >=====================================================================
    > * Class: Node
    > * Description: This is a node in the "List" Link List
    > *
    >====================================================================
    > */
    >
    > template < class unk >
    > class Node
    > {
    > public:
    >
    > // ==================== LIFECYCLE =======================================
    > /* constructor */
    > Node<unk>( unk value, Node<unk> *item_to_link_to = 0);
    > Node ( const Node &other ); /* copy constructor - Need to write this! */


    Stop here!

    Could you clarify to us why the following comments is there:
    /* copy constructor - Need to write this! */


    Yannick
    Yannick Tremblay, Apr 4, 2011
    #1
    1. Advertising

  2. On 2011-04-04, Ruben Safir <> wrote:
    > On Mon, 04 Apr 2011 12:56:41 +0000, Yannick Tremblay wrote:
    >
    >>> ======================================= /* constructor */
    >>> Node<unk>( unk value, Node<unk> *item_to_link_to = 0); Node ( const
    >>> Node &other ); /* copy constructor - Need to write this! */

    >>
    >> Stop here!
    >>
    >> Could you clarify to us why the following comments is there: /* copy
    >> constructor - Need to write this! */

    >
    > Because I haven't written it yet.
    >
    > The purpose of the question is to understand what is happening, not to necessarily
    > fix the program. This is not a homework assignment with a deadline. I just want to
    > have a better understanding of why the destructor caused a double delete.


    This was a leading question.

    copy-constructor are not always needed for all classes. However, for
    some classes a copy constructor is absolutely needed.

    Here you have a header file that explicitely says (correctly given the
    your class contains raw pointers) that the copy contructor need to be
    written. I am not sure if you wrote it yourself as a reminder or if
    it was a format that was specified externally from a template that
    attempt to remind peoples that they should write copy-constructors.

    Regardless, despite the presence of this reminder, you have not
    written the copy-constructor. That should very probably be your first
    point of call.

    Your destructor cause double delete because your copy constructor and
    your destructor are incompatible. Write a copy-constructor that is
    compatible with your destructor or write a copy-constructor and modify
    your destructor so both are compatible and you will not have a bug
    anymore.

    So essentially you have a Node that contains a pointer to value and a
    pointer to next. You have a destructor that delete the pointer to
    value.

    What currently happens if you copy a node?
    (hint: compiler generated copy constructor)
    (hint: what will be the values of value_ and next_ in the copy and in
    the original?)

    What will happen if you delete this node copy?

    What will happen if you delete the original node?


    Yannick
    Yannick Tremblay, Apr 5, 2011
    #2
    1. Advertising

  3. Yannick Tremblay

    Drew Lawson Guest

    In article <indbq3$r87$>
    Ruben Safir <> writes:

    >The purpose of the question is to understand what is happening, not to necessarily
    >fix the program. This is not a homework assignment with a deadline. I just want to
    >have a better understanding of why the destructor caused a double delete.


    Others will cover (or have covered) the language intricacies.
    The practical apect of that question is roughtly:

    Your class Foo has a member
    Bar* ptr;
    The destructor does
    delete ptr;

    If you let the compiler generate the copy constructor and do this:
    Foo a; // assuming ptr points to valid allocated memory
    Foo b;
    b = a;
    The default copy constructor will copy a.ptr to b.ptr, because a
    pointer is just a bunch of bytes.

    When a.~Foo() runs, a.ptr is deleted.
    When b.~Foo() runs, b.ptr, which is the same as a.ptr and was already
    deleted, gets deleted.

    So, if the primitive types in the object have more meaning than
    just "a bunch of bytes," you probably need to write the copy
    constructor (and operator=), or prevent copying.

    --
    Drew Lawson | Savage bed foot-warmer
    | of purest feline ancestry
    | Look out little furry folk
    | it's the all-night working cat
    Drew Lawson, Apr 5, 2011
    #3
  4. Yannick Tremblay

    Sana Guest

    On Apr 5, 11:40 am, Ruben Safir <> wrote:
    >
    > But I'm distressed at this point because I don't want two copies of all
    > the nodes.  I want one series of nodes, which are created in free memory
    > on the stack, handled in all possible scopes.  The nodes themselves are
    > 'self aware" of their positions in the list in that they have the
    > information of they're position in the nodes.  The List object itself
    > does nothing more that communicate with the nodes.  If I copy the List
    > Object, I don't want to duplicate the nodes as well.  They're on the
    > heap, and then can stay there.
    >


    Make your copy constructor private. This will forbid passing the list
    by value. So you will have to pass the list by reference.

    /d
    Sana, Apr 5, 2011
    #4
  5. Yannick Tremblay

    Volker Lukas Guest

    Ruben Safir wrote:
    ....
    > But I'm distressed at this point because I don't want two copies of
    > all
    > the nodes. I want one series of nodes, which are created in free
    > memory
    > on the stack, handled in all possible scopes. The nodes themselves
    > are 'self aware" of their positions in the list in that they have the
    > information of they're position in the nodes. The List object itself
    > does nothing more that communicate with the nodes. If I copy the List
    > Object, I don't want to duplicate the nodes as well. They're on the
    > heap, and then can stay there.

    In this case, you could split your List class in a frontend and a
    backend. The frontend stores a e.g. a shared_ptr to the backend and
    forwards all functions like insert, remove, ... to the backend class. Or
    you could just use a non-copyable List class and have all users of this
    class use shared_ptrs directly. Something like this (untested):

    class List {
    List& operator=(List const&);
    List(List const&);

    public:
    static shared_ptr<List> make() { return shared_ptr<List>(new List); }

    // Rest of implementation here...
    };
    Volker Lukas, Apr 5, 2011
    #5
  6. On 2011-04-05, Ruben Safir <> wrote:
    >
    > But I'm distressed at this point because I don't want two copies of all
    > the nodes. I want one series of nodes, which are created in free memory
    > on the stack, handled in all possible scopes. The nodes themselves are
    > 'self aware" of their positions in the list in that they have the
    > information of they're position in the nodes. The List object itself
    > does nothing more that communicate with the nodes. If I copy the List
    > Object, I don't want to duplicate the nodes as well. They're on the
    > heap, and then can stay there.


    Are you sure about the behaviour you want?

    You have a List.
    The list contains Nodes.
    The Nodes contain a pointer to some data.

    What behaviour do you want when you copy a list?

    What behavious do you want when you copy a node?

    What behaviour do you want when you destroy a list?

    What behaviour do you want when you destroy a node?

    Don't worry about optimization for now. Worry about correctness and
    consistency.

    Does the Node own the data it points to?
    - If yes: then the node most delete the data when the node gets
    destroyed
    - If no: the node only refers to the data that is external. The node
    can go away without affecting the data. Lifetime management of the
    data is done separately.

    Should modifying a copy of a list affect the original list?
    List list1;
    // add ten element to list1;
    assert(list1.size() == 10);
    List list2 = list1; // Create a copy
    assert(list2.size() == list1.size()); // definite at this point

    // remove 2 element from list2
    assert(list2.size() == 8);

    // What about list1? Should it still contain 10 elements or 8?

    Does the list owns the nodes it contains?

    etc.
    Yannick Tremblay, Apr 6, 2011
    #6
    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. joe martin
    Replies:
    3
    Views:
    371
    Francis Glassborow
    Jul 16, 2003
  2. gorda
    Replies:
    5
    Views:
    5,028
    akhyls
    Mar 7, 2010
  3. Replies:
    10
    Views:
    2,338
  4. SpreadTooThin
    Replies:
    3
    Views:
    343
    James Kanze
    Apr 5, 2007
  5. Volker Lukas

    Re: Destructors can copying objects

    Volker Lukas, Apr 2, 2011, in forum: C++
    Replies:
    13
    Views:
    407
    Alf P. Steinbach /Usenet
    Apr 16, 2011
Loading...

Share This Page