Re: Destructors can copying objects

Discussion in 'C++' started by Volker Lukas, Apr 2, 2011.

  1. Volker Lukas

    Volker Lukas Guest

    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.

    Why is the member "value_" in your Node template a pointer? Maybe you
    forgot to clone this pointer in Nodes copy constructor. This is just a
    guess. You did not post a full compilable example which represents your
    problem, so it is difficult to find the problem. Please post a full
    program.

    Also, there is a list template in the C++ Standard Library. Maybe you
    are coding your own list as an exercise, if not you should consider
    whether using std::list is an option.
     
    Volker Lukas, Apr 2, 2011
    #1
    1. Advertising

  2. Volker Lukas

    Balog Pal Guest

    "Ruben Safir" <>
    > I don't think I have a copy constructor, which might be the problem
    > although it never had been.


    Look up "rule of 3". If you have a dtor, you will need a copy cotor and
    operator= too, or must disable them.
     
    Balog Pal, Apr 3, 2011
    #2
    1. Advertising

  3. Volker Lukas

    Volker Lukas Guest

    Ruben Safir wrote:

    > On Sat, 02 Apr 2011 15:29:26 +0200, Volker Lukas wrote:
    >
    >> 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.

    >> Why is the member "value_" in your Node template a pointer? Maybe you
    >> forgot to clone this pointer in Nodes copy constructor. This is just
    >> a guess. You did not post a full compilable example which represents
    >> your problem, so it is difficult to find the problem. Please post a
    >> full program.
    >>
    >> Also, there is a list template in the C++ Standard Library. Maybe you
    >> are coding your own list as an exercise, if not you should consider
    >> whether using std::list is an option.

    >
    > I think this outlines the bug

    Unfortunately, I still can not get this to compile because many
    functions are unimplemented. I think I can say that the problem is that
    inside your List object you are storing pointers to the nodes. When you
    pass this object to a function by value a second object, a copy is
    created, which stores the same pointer values (since you did not define
    a copy constructor). Now you have two objects whose destructors will
    both attempt to delete the same objects. That is an error.

    If you need a definite answer you need to post a full compilable
    example, something which can be saved verbatim in a file which can be
    compiled.
     
    Volker Lukas, Apr 3, 2011
    #3
  4. Am 03.04.2011 05:08, schrieb Ruben Safir:
    >
    > #ifndef LINKLIST
    > #define LINKLIST
    > #include "linklist.h"
    > #endif /* ----- not LINKLIST ----- */


    Include guards should be inside the header, not outside it in the source?


    Peter
     
    Peter Remmers, Apr 3, 2011
    #4
  5. Volker Lukas

    James Kanze Guest

    On Apr 3, 3:59 am, Ruben Safir <> wrote:
    > On Sat, 02 Apr 2011 15:29:26 +0200, Volker Lukas wrote:
    > > 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.

    > > Why is the member "value_" in your Node template a pointer?


    > Because by experience, pointers are easier to set to null
    > which is needed from time to time as the end node should be
    > null.


    Why would you want such a node? Typically, the last node in the
    list will have a next pointer which is null, but all nodes which
    exist will have a valid value.

    > > Maybe you
    > > forgot to clone this pointer in Nodes copy constructor.


    > I don't think I have a copy constructor, which might be the
    > problem although it never had been.


    It depends. Before trying to diagnose anything, it's necessary
    to define what the class is supposed to do.

    > The Nodes are separate from the list so when I pass the list
    > by value, I created a new list object that when the function
    > stopped, called the list destructor, destroying the nodes.
    > When the program stopped, THEN the List destructor was called
    > again and tried to destroy the same node.


    What are the semantics of List? Should it support deep copy, or
    does copying result in a shared list? (Or maybe it shouldn't
    support copy at all.) Until you decide on the semantics, it's
    impossible to say what should be done. (But it is likely that
    List will require a copy constructor of some sort.)

    --
    James Kanze
     
    James Kanze, Apr 3, 2011
    #5
  6. Peter Remmers wrote:
    >Am 03.04.2011 05:08, schrieb Ruben Safir:
    >> #ifndef LINKLIST
    >> #define LINKLIST
    >> #include "linklist.h"
    >> #endif /* ----- not LINKLIST ----- */

    >
    >Include guards should be inside the header, not outside it in the source?


    It "should" be done either way.
    In older, slower systems, (think compiling from very slow disks, or
    even slower floppies,) it was common to use this approach to skip
    reading the included file altogether.
    With the multiple inclusion guards in the header file being protected,
    the compiler/preprocessor still needs to read the whole file and scan
    it for any preprocessing directives.
    --
    Roberto Waltman

    [ Please reply to the group,
    return address is invalid ]
     
    Roberto Waltman, Apr 3, 2011
    #6
  7. Leigh Johnston Wrote:

    > On 03/04/2011 10:32, Balog Pal wrote:
    > > "Ruben Safir" <>
    > >> I don't think I have a copy constructor, which might be the
    > >> problem although it never had been.

    > >
    > > Look up "rule of 3". If you have a dtor, you will need a copy cotor
    > > and operator= too, or must disable them.
    > >

    >
    > Like most "rules" mentioned in this newsgroup the "rule of 3" is a
    > nonsense:


    That is putting it too strong.
    The "rule of 3" is certainly not universally applicable, but you certainly
    must keep it in mind when adding a destructor, copy-constructor or
    copy-assignment operator to your class.

    >you may be adding a virtual dtor simply to make a base class
    > polymorphic and have no need for a copy ctor and assignment
    > operator or you may be relying on RAII and the behaviour of the
    > implicitly defined special member functions.


    Those are certainly situation where not all three of the mentioned member
    functions are needed.
    The best way to apply the "rule of three" is: Whenever you add a destructor,
    copy-constructor or copy-assignment operator, check if the default behaviour
    for the other two is suitable for your class. If not, define them
    appropriately (or make them inaccessible)."

    >
    > /Leigh


    Bart v Ingen Schenau
     
    Bart van Ingen Schenau, Apr 4, 2011
    #7
  8. On Apr 3, 4:29 am, Leigh Johnston <> wrote:
    > On 03/04/2011 10:32, Balog Pal wrote:
    >
    > > "Ruben Safir" <>
    > >> I don't think I have a copy constructor, which might be the problem
    > >> although it never had been.

    >
    > > Look up "rule of 3". If you have a dtor, you will need a copy cotor and
    > > operator= too, or must disable them.

    >
    > Like most "rules" mentioned in this newsgroup the "rule of 3" is a
    > nonsense: you may be adding a virtual dtor simply to make a base class
    > polymorphic and have no need for a copy ctor and assignment operator


    In which case you probably want to prevent accidental slicing, and you
    do that by defining a protected or private copy constructor and
    assignment operator.

    > or
    > you may be relying on RAII and the behaviour of the implicitly defined
    > special member functions.


    I don't see an example here, just a hand wave, so I'm unable to verify
    the veracity of your claims.
     
    Joshua Maurice, Apr 4, 2011
    #8
  9. Volker Lukas

    LR Guest

    Ruben Safir wrote:
    > On Sun, 03 Apr 2011 10:07:40 -0700, James Kanze wrote:
    >
    >
    >> What are the semantics of List? Should it support deep copy, or does
    >> copying result in a shared list?

    >
    > It doesn't make much of difference, it seems, if it is doing a double
    > delete. That would seem to indicate that it must need a deep copy of all
    > the nodes and the information, which is really not what I wanted.
    >
    > Maybe if I make the copy constructor private, and operator=() that it
    > might work better



    Maybe you want some sort of smart shared pointer?

    LR
     
    LR, Apr 5, 2011
    #9
  10. On 4 avr, 13:43, Bart van Ingen Schenau <> wrote:
    > Leigh Johnston Wrote:
    >
    > > On 03/04/2011 10:32, Balog Pal wrote:
    > > > "Ruben Safir" <>
    > > >> I don't think I have a copy constructor, which might be the
    > > >> problem although it never had been.

    >
    > > > Look up "rule of 3". If you have a dtor, you will need a copy cotor
    > > > and operator= too, or must disable them.

    >
    > > Like most "rules" mentioned in this newsgroup the "rule of 3" is a
    > > nonsense:

    >
    > That is putting it too strong.
    > The "rule of 3" is certainly not universally applicable, but you certainly
    > must keep it in mind when adding a destructor, copy-constructor or
    > copy-assignment operator to your class.
    >
    > >you may be adding a virtual dtor simply to make a base class
    > > polymorphic and have no need for a copy ctor and assignment
    > > operator or you may be relying on RAII and the behaviour of the
    > > implicitly defined special member functions.

    >
    > Those are certainly situation where not all three of the mentioned member
    > functions are needed.
    > The best way to apply the "rule of three" is: Whenever you add a destructor,
    > copy-constructor or copy-assignment operator, check if the default behaviour
    > for the other two is suitable for your class. If not, define them
    > appropriately (or make them inaccessible)."


    The original phrasing is:
    http://drdobbs.com/cpp/184401400
    The Rule of Three says that there are three member functions that go
    together: the destructor, the copy constructor, and the assignment
    operator. A class that defines a destructor should almost always
    define the other two members. Moreover, a class that defines a copy
    constructor or assignment operator should usually define the other two
    members as well.

    AFAIU the underlying idea if that classes should be in canonical form.

    --
    Michael
     
    Michael Doubez, Apr 5, 2011
    #10
  11. Volker Lukas

    LR Guest

    Ruben Safir wrote:
    > On Sun, 03 Apr 2011 18:16:58 -0400, Roberto Waltman wrote:
    >
    >> Peter Remmers wrote:
    >>> Am 03.04.2011 05:08, schrieb Ruben Safir:
    >>>> #ifndef LINKLIST
    >>>> #define LINKLIST
    >>>> #include "linklist.h"
    >>>> #endif /* ----- not LINKLIST ----- */
    >>>
    >>> Include guards should be inside the header, not outside it in the
    >>> source?

    >>
    >> It "should" be done either way.
    >> In older, slower systems, (think compiling from very slow disks, or even
    >> slower floppies,) it was common to use this approach to skip reading the
    >> included file altogether. With the multiple inclusion guards in the
    >> header file being protected, the compiler/preprocessor still needs to
    >> read the whole file and scan it for any preprocessing directives.

    >
    > I just had a problem pop up where all my templates were coming up with
    > redefinition errors. The problem stopped when I moved the #endif to the
    > bottom of the file. Why would I see that behavior?


    You're probably including linklist.h more than once in the file you're
    trying to compile.

    http://en.wikipedia.org/wiki/Include_guard

    LR
     
    LR, Apr 16, 2011
    #11
  12. * Ruben Safir, on 16.04.2011 01:03:
    > On Sun, 03 Apr 2011 12:14:40 +0200, Peter Remmers wrote:
    >
    >> Am 03.04.2011 05:08, schrieb Ruben Safir:
    >>>
    >>> #ifndef LINKLIST
    >>> #define LINKLIST
    >>> #include "linklist.h"
    >>> #endif /* ----- not LINKLIST ----- */

    >>
    >> Include guards should be inside the header, not outside it in the
    >> source?

    >
    > please explain
    >
    > should the #endif be at the end of the file and why?


    It depends on whether it's an external include guard (where you're including the
    header) or an internal include guard (the ordinary kind of include guard, in the
    header file). The idea in any case is to ensure that the text of the header is
    included only once. You can figure it out from there.

    External include guards were discussed in Lakos' "Large scale software design".
    They're no longer much used. Compiler technology has improved.

    For an internal include guard the usual pattern is now


    #ifndef SOME_UNIQUE_SYMBOL
    #define SOME_UNIQUE_SYMBOL

    //... text of header file

    #endif


    An alternative that is /non-standard/ and /not entirely reliable/, but that is
    textually much cleaner, is to use a '#pragma once', like so:


    #pragma once

    //... text of header file


    The pragma is problematic when one employs symbolic links to files. The compiler
    may then be unable to detect that two or more links yield the same file. Hence,
    the pragma may be preferable for a small personal project, but not as the single
    single-include-measure for a larger project with more devlopers involved (some
    of whom may suddenly be using symbolic links). When combined with internal
    include guards it may however reduce build times, and it may be necessary due to
    non-standard behavior such as Microsoft's "precompiled headers". Whether it
    actually does reduce build times or have other beneficial or necessary effect,
    depends on the compiler etc.


    Cheers & hth.,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
     
    Alf P. Steinbach /Usenet, Apr 16, 2011
    #12
  13. Am 16.04.2011 01:47, schrieb Alf P. Steinbach /Usenet:
    > * Ruben Safir, on 16.04.2011 01:03:
    >> On Sun, 03 Apr 2011 12:14:40 +0200, Peter Remmers wrote:
    >>
    >>> Am 03.04.2011 05:08, schrieb Ruben Safir:
    >>>>
    >>>> #ifndef LINKLIST
    >>>> #define LINKLIST
    >>>> #include "linklist.h"
    >>>> #endif /* ----- not LINKLIST ----- */
    >>>
    >>> Include guards should be inside the header, not outside it in the
    >>> source?

    >>
    >> please explain
    >>
    >> should the #endif be at the end of the file and why?

    >
    > It depends on whether it's an external include guard (where you're including the
    > header) or an internal include guard (the ordinary kind of include guard, in the
    > header file). The idea in any case is to ensure that the text of the header is
    > included only once. You can figure it out from there.
    >
    > External include guards were discussed in Lakos' "Large scale software design".
    > They're no longer much used. Compiler technology has improved.


    They also have several disadvantages:
    - You would need to put a guard around each #include for every file that
    does not employ its own internal guard
    - You would need to put a guard around each #include occurrence for a
    certain header, in every source and every other spot where you include it
    - You would need to make sure that you use exactly the same macro for
    each occurrence

    This is unnecessarily troublesome and totally error prone. Not to
    mention unreadable.

    > For an internal include guard the usual pattern is now
    >
    >
    > #ifndef SOME_UNIQUE_SYMBOL
    > #define SOME_UNIQUE_SYMBOL
    >
    > //... text of header file
    >
    > #endif
    >
    >
    > An alternative that is /non-standard/ and /not entirely reliable/, but that is
    > textually much cleaner, is to use a '#pragma once', like so:
    >
    >
    > #pragma once
    >
    > //... text of header file
    >
    >
    > The pragma is problematic when one employs symbolic links to files.

    Why would anyone do such a thing?

    >The compiler
    > may then be unable to detect that two or more links yield the same file. Hence,
    > the pragma may be preferable for a small personal project, but not as the single
    > single-include-measure for a larger project with more devlopers involved (some
    > of whom may suddenly be using symbolic links). When combined with internal
    > include guards it may however reduce build times, and it may be necessary due to
    > non-standard behavior such as Microsoft's "precompiled headers". Whether it
    > actually does reduce build times or have other beneficial or necessary effect,
    > depends on the compiler etc.
    >
    >
    > Cheers& hth.,
    >
    > - Alf
    >



    Peter
     
    Peter Remmers, Apr 16, 2011
    #13
  14. * Peter Remmers, on 16.04.2011 13:00:
    > Am 16.04.2011 01:47, schrieb Alf P. Steinbach /Usenet:
    >>
    >> An alternative that is /non-standard/ and /not entirely reliable/, but that is
    >> textually much cleaner, is to use a '#pragma once', like so:
    >>
    >>
    >> #pragma once
    >>
    >> //... text of header file
    >>
    >>
    >> The pragma is problematic when one employs symbolic links to files.

    >
    > Why would anyone do such a thing?


    Well, people have stated directly (on SO) that they do employ symbolic links and
    prefer that. But as far as I recall they have not stated why they employ
    symbolic links, except for general convenience. So this is speculation, but
    consider a library of sublibries, where one would like usage to be like

    #include <vendor/sublibrary/module.h>

    Then the directory structure for development might be like

    bigLibrary
    library1
    vendor
    library1 -> files like [module.h]
    library2
    vendor
    library2
    library3
    vendor
    library3

    For example, as I recall you find that kind of directory structure for the
    version 2 things in the OpenCV library.

    It allows each of the library1 etc. directories to be placed just about anywhere
    and worked on independently, not just as parts of bigLibrary.

    But for usage it's a nuisance to set up include paths to all of library1,
    library2, library3 etc. For usage you might therefore instead have

    bigLibrary
    include
    vendor
    library1 as link to impl/bigLibrary/library1/vendor/library1
    library2 as link to impl/bigLibrary/library2/vendor/library2

    and set up include file search path only to bigLibrary/include directory.

    In Windows XP and earlier this is a bit difficult to do -- no symlinks! But
    the masochistic developer can set up folders that redirect to folders. He he.

    <example>
    C:\test> md a

    C:\test> echo This is the 'a' directory... >a\description.txt

    C:\test> which linkd.exe
    C:\Program Files\Windows Resource Kits\Tools\linkd.exe

    C:\test> md b

    C:\test> linkd b a
    Link created at: b

    C:\test> cd b

    C:\test\b> type description.txt
    This is the 'a' directory...

    C:\test\b> _
    </example>


    Disclaimer: I haven't tested that for includes. And the idea that this might be
    the reason for people using symlinks is, as I wrote, just speculation. A
    possibility.


    Cheers & hth.,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
     
    Alf P. Steinbach /Usenet, Apr 16, 2011
    #14
    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:
    381
    Francis Glassborow
    Jul 16, 2003
  2. gorda
    Replies:
    5
    Views:
    5,052
    akhyls
    Mar 7, 2010
  3. Replies:
    10
    Views:
    2,359
  4. SpreadTooThin
    Replies:
    3
    Views:
    353
    James Kanze
    Apr 5, 2007
  5. Yannick Tremblay

    Re: Destructors can copying objects

    Yannick Tremblay, Apr 4, 2011, in forum: C++
    Replies:
    5
    Views:
    272
    Yannick Tremblay
    Apr 6, 2011
Loading...

Share This Page