noob question - destructors - freeing memory...

Discussion in 'C++' started by someone, Dec 31, 2011.

  1. someone

    someone Guest

    Hi

    See this (stolen from the internet):

    ----------------------------------------
    #include <iostream>
    using namespace std;

    class Base
    {
    public:
    Base(){ cout<<"Constructing Base"<<endl;}

    // this is a destructor:
    virtual ~Base(){ cout<<"Destroying Base"<<endl;}
    };

    class Derive: public Base
    {
    public:
    Derive(){ cout<<"Constructing Derive"<<endl;}
    ~Derive(){ cout<<"Destroying Derive"<<endl;}
    };

    int main()
    {
    Base *basePtr = new Derive();
    // delete basePtr; // <<<======== !! ! ! ! ! NB !!
    return 0;
    }

    ----------------------------------------

    See middle line of main():

    delete basePtr; // <<<======== !! ! ! ! ! NB !!


    If I enable (uncomment) middle line, I get:
    Constructing Base
    Constructing Derive
    Destroying Derive
    Destroying Base


    If I disable (comment out) middle line, I get:
    Constructing Base
    Constructing Derive


    ========

    This, I didn't quite expect, because I thought that at the end of the
    program, all destructors where guaranteed to be called...

    In my case, I have a longer program and I allocate memory with one of my
    constructors, hence it is crucial to free the memory, but since the
    virtual destructor is never called, I never free the memory...

    In addition: In my full program (not shown here), I instantiate my new
    object like:

    int main(...)
    {
    ...
    Derive d1();
    return 0; // or exit(1); if something went wrong somewhere
    }

    Is it required that I do, like in the example above:

    int main(...)
    {
    ...
    Base *myPtr = new Derive();
    delete myPtr;
    return 0; // or exit(1); if something went wrong somewhere
    }

    ???????

    But what if my code does an exit(1) somewhere, which it could do at
    least a dozens of times, in different parts of the program?


    Please advice, thank you!
     
    someone, Dec 31, 2011
    #1
    1. Advertising

  2. someone

    MikeWhy Guest

    someone wrote:
    > Hi
    >
    > See this (stolen from the internet):
    >
    > ----------------------------------------
    > #include <iostream>
    > using namespace std;
    >
    > class Base
    > {
    > public:
    > Base(){ cout<<"Constructing Base"<<endl;}
    >
    > // this is a destructor:
    > virtual ~Base(){ cout<<"Destroying Base"<<endl;}
    > };
    >
    > class Derive: public Base
    > {
    > public:
    > Derive(){ cout<<"Constructing Derive"<<endl;}
    > ~Derive(){ cout<<"Destroying Derive"<<endl;}
    > };
    >
    > int main()
    > {
    > Base *basePtr = new Derive();
    > // delete basePtr; // <<<======== !! ! ! ! ! NB !!
    > return 0;
    > }
    >
    > ----------------------------------------
    >
    > See middle line of main():
    >
    > delete basePtr; // <<<======== !! ! ! ! ! NB !!
    >
    >
    > If I enable (uncomment) middle line, I get:
    > Constructing Base
    > Constructing Derive
    > Destroying Derive
    > Destroying Base
    >
    >
    > If I disable (comment out) middle line, I get:
    > Constructing Base
    > Constructing Derive
    >
    >
    > ========
    >
    > This, I didn't quite expect, because I thought that at the end of the
    > program, all destructors where guaranteed to be called...


    If pointers had destructors, what action should they take?

    > In my case, I have a longer program and I allocate memory with one of
    > my constructors, hence it is crucial to free the memory, but since the
    > virtual destructor is never called, I never free the memory...
    >
    > In addition: In my full program (not shown here), I instantiate my new
    > object like:
    >
    > int main(...)
    > {
    > ...
    > Derive d1();
    > return 0; // or exit(1); if something went wrong somewhere
    > }
    >
    > Is it required that I do, like in the example above:
    >
    > int main(...)
    > {
    > ...
    > Base *myPtr = new Derive();


    foo(); // insert this line. See below.

    > delete myPtr;
    > return 0; // or exit(1); if something went wrong somewhere
    > }
    >
    > ???????


    Yes.

    >
    > But what if my code does an exit(1) somewhere, which it could do at
    > least a dozens of times, in different parts of the program?


    exit() is a function call. In your final example above, if foo() called
    exit(1), will your destructor be called? Given what you saw earlier, how
    does exit() trigger process termination?

    If instead of calling exit(), foo() throws an uncaught exception. How does
    the program behave?

    Calling exit() is a very bad idea. Ditto for terminating threads, only more
    so. A simple return will suffice. Find some other mechanism to trigger
    process (and thread) termination.
     
    MikeWhy, Dec 31, 2011
    #2
    1. Advertising

  3. someone

    someone Guest

    On 12/31/2011 03:06 AM, MikeWhy wrote:
    > someone wrote:
    >> Hi
    >>
    >> See this (stolen from the internet):
    >>
    >> ----------------------------------------
    >> #include <iostream>
    >> using namespace std;
    >>
    >> class Base
    >> {
    >> public:
    >> Base(){ cout<<"Constructing Base"<<endl;}
    >>
    >> // this is a destructor:
    >> virtual ~Base(){ cout<<"Destroying Base"<<endl;}
    >> };
    >>
    >> class Derive: public Base
    >> {
    >> public:
    >> Derive(){ cout<<"Constructing Derive"<<endl;}
    >> ~Derive(){ cout<<"Destroying Derive"<<endl;}
    >> };
    >>
    >> int main()
    >> {
    >> Base *basePtr = new Derive();
    >> // delete basePtr; // <<<======== !! ! ! ! ! NB !!
    >> return 0;
    >> }
    >>
    >> ----------------------------------------
    >>
    >> See middle line of main():
    >>
    >> delete basePtr; // <<<======== !! ! ! ! ! NB !!
    >>
    >>
    >> If I enable (uncomment) middle line, I get:
    >> Constructing Base
    >> Constructing Derive
    >> Destroying Derive
    >> Destroying Base
    >>
    >>
    >> If I disable (comment out) middle line, I get:
    >> Constructing Base
    >> Constructing Derive
    >>
    >>
    >> ========
    >>
    >> This, I didn't quite expect, because I thought that at the end of the
    >> program, all destructors where guaranteed to be called...

    >
    > If pointers had destructors, what action should they take?


    Delete themselves? But not before they've destructed the objects they're
    pointing to! After they've destructed (free'd) the dereferenced objects,
    the pointers can free themselves...

    Why doesn't that happen in the example in my post and in my full code?

    >> In my case, I have a longer program and I allocate memory with one of
    >> my constructors, hence it is crucial to free the memory, but since the
    >> virtual destructor is never called, I never free the memory...
    >>
    >> In addition: In my full program (not shown here), I instantiate my new
    >> object like:
    >>
    >> int main(...)
    >> {
    >> ...
    >> Derive d1();
    >> return 0; // or exit(1); if something went wrong somewhere
    >> }
    >>
    >> Is it required that I do, like in the example above:
    >>
    >> int main(...)
    >> {
    >> ...
    >> Base *myPtr = new Derive();

    >
    > foo(); // insert this line. See below.
    >> delete myPtr;
    >> return 0; // or exit(1); if something went wrong somewhere
    >> }
    >>
    >> ???????

    >
    > Yes.


    Ok, but I don't understand why... I found this post:
    http://www.tech-archive.net/Archive/VC/microsoft.public.vc.mfc/2007-05/msg01433.html

    from where I qoute: "Static objects are deleted (so the destructor is
    called) when global variables are deallocated, so when the program exits."

    I believe this code:

    int main(...)
    {
    ...
    Derive d1();
    return 0; // or exit(1); if something went wrong somewhere
    }

    Has d1 to be a static object, hence when the program exits, the
    destructor of d1 should be called just before exitting... Why don't this
    happen?

    >> But what if my code does an exit(1) somewhere, which it could do at
    >> least a dozens of times, in different parts of the program?

    >
    > exit() is a function call. In your final example above, if foo() called
    > exit(1), will your destructor be called? Given what you saw earlier, how
    > does exit() trigger process termination?


    exit() is not a normal function call. Normally, code execution continues
    right after the function calls. But not with exit(). Code below exit()
    is not executed.

    > If instead of calling exit(), foo() throws an uncaught exception. How
    > does the program behave?


    I later found some posts on google, suggesting to throw/catch
    exceptions, however I'm not very good at using exceptions and fear that
    the code will be much more complicated.

    > Calling exit() is a very bad idea. Ditto for terminating threads, only
    > more so. A simple return will suffice. Find some other mechanism to
    > trigger process (and thread) termination.


    return() has exactly the same problem as exit: The code below return()
    in main is not executed, hence I believe that exit() is some kind of
    acronym for return() (from the main thread)...

    Anyway, please explain why the static destructor is not called on exit.
    I don't understand why not...
     
    someone, Dec 31, 2011
    #3
  4. someone

    MikeWhy Guest

    someone wrote:
    > On 12/31/2011 03:06 AM, MikeWhy wrote:
    >> someone wrote:
    >>> Hi
    >>>
    >>> See this (stolen from the internet):
    >>>
    >>> ----------------------------------------
    >>> #include <iostream>
    >>> using namespace std;
    >>>
    >>> class Base
    >>> {
    >>> public:
    >>> Base(){ cout<<"Constructing Base"<<endl;}
    >>>
    >>> // this is a destructor:
    >>> virtual ~Base(){ cout<<"Destroying Base"<<endl;}
    >>> };
    >>>
    >>> class Derive: public Base
    >>> {
    >>> public:
    >>> Derive(){ cout<<"Constructing Derive"<<endl;}
    >>> ~Derive(){ cout<<"Destroying Derive"<<endl;}
    >>> };
    >>>
    >>> int main()
    >>> {
    >>> Base *basePtr = new Derive();
    >>> // delete basePtr; // <<<======== !! ! ! ! ! NB !!
    >>> return 0;
    >>> }
    >>>
    >>> ----------------------------------------
    >>>
    >>> See middle line of main():
    >>>
    >>> delete basePtr; // <<<======== !! ! ! ! ! NB !!
    >>>
    >>>
    >>> If I enable (uncomment) middle line, I get:
    >>> Constructing Base
    >>> Constructing Derive
    >>> Destroying Derive
    >>> Destroying Base
    >>>
    >>>
    >>> If I disable (comment out) middle line, I get:
    >>> Constructing Base
    >>> Constructing Derive
    >>>
    >>>
    >>> ========
    >>>
    >>> This, I didn't quite expect, because I thought that at the end of
    >>> the program, all destructors where guaranteed to be called...

    >>
    >> If pointers had destructors, what action should they take?

    >
    > Delete themselves? But not before they've destructed the objects
    > they're pointing to! After they've destructed (free'd) the
    > dereferenced objects, the pointers can free themselves...
    >
    > Why doesn't that happen in the example in my post and in my full code?
    >
    >>> In my case, I have a longer program and I allocate memory with one
    >>> of my constructors, hence it is crucial to free the memory, but
    >>> since the virtual destructor is never called, I never free the
    >>> memory... In addition: In my full program (not shown here), I
    >>> instantiate my
    >>> new object like:
    >>>
    >>> int main(...)
    >>> {
    >>> ...
    >>> Derive d1();
    >>> return 0; // or exit(1); if something went wrong somewhere
    >>> }
    >>>
    >>> Is it required that I do, like in the example above:
    >>>
    >>> int main(...)
    >>> {
    >>> ...
    >>> Base *myPtr = new Derive();

    >>
    >> foo(); // insert this line. See below.
    >>> delete myPtr;
    >>> return 0; // or exit(1); if something went wrong somewhere
    >>> }
    >>>
    >>> ???????

    >>
    >> Yes.

    >
    > Ok, but I don't understand why... I found this post:
    > http://www.tech-archive.net/Archive/VC/microsoft.public.vc.mfc/2007-05/msg01433.html
    >
    > from where I qoute: "Static objects are deleted (so the destructor is
    > called) when global variables are deallocated, so when the program
    > exits."
    > I believe this code:
    >
    > int main(...)
    > {
    > ...
    > Derive d1();
    > return 0; // or exit(1); if something went wrong somewhere
    > }
    >
    > Has d1 to be a static object, hence when the program exits, the
    > destructor of d1 should be called just before exitting... Why don't
    > this happen?
    >
    >>> But what if my code does an exit(1) somewhere, which it could do at
    >>> least a dozens of times, in different parts of the program?

    >>
    >> exit() is a function call. In your final example above, if foo()
    >> called exit(1), will your destructor be called? Given what you saw
    >> earlier, how does exit() trigger process termination?

    >
    > exit() is not a normal function call. Normally, code execution
    > continues right after the function calls. But not with exit(). Code
    > below exit() is not executed.
    >
    >> If instead of calling exit(), foo() throws an uncaught exception. How
    >> does the program behave?

    >
    > I later found some posts on google, suggesting to throw/catch
    > exceptions, however I'm not very good at using exceptions and fear
    > that the code will be much more complicated.
    >
    >> Calling exit() is a very bad idea. Ditto for terminating threads,
    >> only more so. A simple return will suffice. Find some other
    >> mechanism to trigger process (and thread) termination.

    >
    > return() has exactly the same problem as exit: The code below return()
    > in main is not executed, hence I believe that exit() is some kind of
    > acronym for return() (from the main thread)...


    return is a C/C++ keyword. exit() is a function call. It kills the process
    and does not return. Since exit() doesn't return, foo() doesn't return.
    Since foo() doesn't return, execution will not continue in main(). Your
    delete will not be called.

    You're asking the right questions. You now need to understand the
    distinction.

    There also was a reason to bring up exceptions. The exception would have
    behaved as you thought exit() might. In the contexts you describe -- calling
    exit(1) in multiple locations -- the semantics and behavior are as you
    expected from exit().


    > Anyway, please explain why the static destructor is not called on
    > exit. I don't understand why not...


    The truth of the matter is that pointers do not have destructors. My
    intention was not to lead you astray, however. You'll visit this again in
    shared_ptr and auto_ptr classes.
     
    MikeWhy, Dec 31, 2011
    #4
  5. On Sat, 31 Dec 2011 02:43:28 +0100, someone <>
    wrote:
    > Hi



    > See this (stolen from the internet):



    > ----------------------------------------
    > #include <iostream>
    > using namespace std;



    > class Base
    > {
    > public:
    > Base(){ cout<<"Constructing Base"<<endl;}



    > // this is a destructor:
    > virtual ~Base(){ cout<<"Destroying Base"<<endl;}
    > };



    > class Derive: public Base
    > {
    > public:
    > Derive(){ cout<<"Constructing Derive"<<endl;}
    > ~Derive(){ cout<<"Destroying Derive"<<endl;}
    > };



    > int main()
    > {
    > Base *basePtr = new Derive();
    > // delete basePtr; // <<<======== !! ! ! ! ! NB !!
    > return 0;
    > }



    > ----------------------------------------



    > See middle line of main():



    > delete basePtr; // <<<======== !! ! ! ! ! NB !!





    > If I enable (uncomment) middle line, I get:
    > Constructing Base
    > Constructing Derive
    > Destroying Derive
    > Destroying Base





    > If I disable (comment out) middle line, I get:
    > Constructing Base
    > Constructing Derive





    > ========



    > This, I didn't quite expect, because I thought that at the end of

    the
    > program, all destructors where guaranteed to be called...



    > In my case, I have a longer program and I allocate memory with one

    of my
    > constructors, hence it is crucial to free the memory, but since the
    > virtual destructor is never called, I never free the memory...



    > In addition: In my full program (not shown here), I instantiate my

    new
    > object like:



    > int main(...)
    > {
    > ...
    > Derive d1();
    > return 0; // or exit(1); if something went wrong somewhere
    > }



    > Is it required that I do, like in the example above:



    > int main(...)
    > {
    > ...
    > Base *myPtr = new Derive();
    > delete myPtr;
    > return 0; // or exit(1); if something went wrong somewhere
    > }



    > ???????



    > But what if my code does an exit(1) somewhere, which it could do at
    > least a dozens of times, in different parts of the program?





    > Please advice, thank you!


    A statically constructed object will be destroyed when the scope is
    left.

    e.g destructors will be called in:
    int main()
    {
    Derived d;
    return 0;
    }

    A dynamically constructed object (created using new) is destroyed
    when delete is called.

    e.g destructors called in this:
    int main()
    {
    Base * b = new Derived();
    delete b;
    return 0;
    }

    but not this:
    int main()
    {
    Base * b = new Derived();
    return 0;
    }


    When exit(int) is called, the program is terminated *without
    unwinding the stack* so no destructors are called.

    When a execption is thrown and not caught, the program is terminated
    *with stack unwinding*, so static objects are destroyed.

    Note:
    int main()
    {
    Base * b = new Derived();
    throw std::exception();
    delete b;
    return 0;
    }

    In the above, the delete expression is never reached, so destructors
    are not called.
    If this is an issue, a smart pointer (boost::shared_ptr,
    boost::scoped_ptr, etc:) should be used.
     
    Garrett Hartshaw, Dec 31, 2011
    #5
  6. someone

    someone Guest

    On 12/31/2011 04:22 AM, MikeWhy wrote:
    > someone wrote:
    >> On 12/31/2011 03:06 AM, MikeWhy wrote:
    >>> someone wrote:

    ...

    >>>> If I enable (uncomment) middle line, I get:
    >>>> Constructing Base
    >>>> Constructing Derive
    >>>> Destroying Derive
    >>>> Destroying Base
    >>>>
    >>>>
    >>>> If I disable (comment out) middle line, I get:
    >>>> Constructing Base
    >>>> Constructing Derive
    >>>>
    >>>>
    >>>> ========
    >>>>
    >>>> This, I didn't quite expect, because I thought that at the end of
    >>>> the program, all destructors where guaranteed to be called...
    >>>
    >>> If pointers had destructors, what action should they take?

    >>
    >> Delete themselves? But not before they've destructed the objects
    >> they're pointing to! After they've destructed (free'd) the
    >> dereferenced objects, the pointers can free themselves...
    >>
    >> Why doesn't that happen in the example in my post and in my full code?


    No answer?

    >>>> In my case, I have a longer program and I allocate memory with one
    >>>> of my constructors, hence it is crucial to free the memory, but
    >>>> since the virtual destructor is never called, I never free the
    >>>> memory... In addition: In my full program (not shown here), I
    >>>> instantiate my
    >>>> new object like:
    >>>>
    >>>> int main(...)
    >>>> {
    >>>> ...
    >>>> Derive d1();
    >>>> return 0; // or exit(1); if something went wrong somewhere
    >>>> }
    >>>>
    >>>> Is it required that I do, like in the example above:
    >>>>
    >>>> int main(...)
    >>>> {
    >>>> ...
    >>>> Base *myPtr = new Derive();
    >>>
    >>> foo(); // insert this line. See below.
    >>>> delete myPtr;
    >>>> return 0; // or exit(1); if something went wrong somewhere
    >>>> }
    >>>>
    >>>> ???????
    >>>
    >>> Yes.

    >>
    >> Ok, but I don't understand why... I found this post:
    >> http://www.tech-archive.net/Archive/VC/microsoft.public.vc.mfc/2007-05/msg01433.html
    >>
    >>
    >> from where I qoute: "Static objects are deleted (so the destructor is
    >> called) when global variables are deallocated, so when the program
    >> exits."
    >> I believe this code:
    >>
    >> int main(...)
    >> {
    >> ...
    >> Derive d1();
    >> return 0; // or exit(1); if something went wrong somewhere
    >> }
    >>
    >> Has d1 to be a static object, hence when the program exits, the
    >> destructor of d1 should be called just before exitting... Why don't
    >> this happen?
    >>
    >>>> But what if my code does an exit(1) somewhere, which it could do at
    >>>> least a dozens of times, in different parts of the program?
    >>>
    >>> exit() is a function call. In your final example above, if foo()
    >>> called exit(1), will your destructor be called? Given what you saw
    >>> earlier, how does exit() trigger process termination?

    >>
    >> exit() is not a normal function call. Normally, code execution
    >> continues right after the function calls. But not with exit(). Code
    >> below exit() is not executed.
    >>
    >>> If instead of calling exit(), foo() throws an uncaught exception. How
    >>> does the program behave?

    >>
    >> I later found some posts on google, suggesting to throw/catch
    >> exceptions, however I'm not very good at using exceptions and fear
    >> that the code will be much more complicated.
    >>
    >>> Calling exit() is a very bad idea. Ditto for terminating threads,
    >>> only more so. A simple return will suffice. Find some other
    >>> mechanism to trigger process (and thread) termination.

    >>
    >> return() has exactly the same problem as exit: The code below return()
    >> in main is not executed, hence I believe that exit() is some kind of
    >> acronym for return() (from the main thread)...

    >
    > return is a C/C++ keyword. exit() is a function call. It kills the
    > process and does not return. Since exit() doesn't return, foo() doesn't
    > return. Since foo() doesn't return, execution will not continue in
    > main(). Your delete will not be called.


    But it's not the answer to why, when I create static objects, the
    destructor of d1 is not called when exitting... Right?

    > You're asking the right questions. You now need to understand the
    > distinction.
    >
    > There also was a reason to bring up exceptions. The exception would have
    > behaved as you thought exit() might. In the contexts you describe --
    > calling exit(1) in multiple locations -- the semantics and behavior are
    > as you expected from exit().
    >
    >
    >> Anyway, please explain why the static destructor is not called on
    >> exit. I don't understand why not...

    >
    > The truth of the matter is that pointers do not have destructors. My
    > intention was not to lead you astray, however. You'll visit this again
    > in shared_ptr and auto_ptr classes.


    So you don't want to explain it?

    FYI: I have no shared_ptr and auto_ptr classes, I don't know what it
    means and I'll never take them. I'm too old for that. You're not that
    old yourself and hence assumed that everyone in here is a student, doing
    school work? Never heard of something like: Went out of school years
    ago, but am learning a new programming language anyway?

    I don't understand why you not just explain it, instead of all this
    irrelevant talk about if pointers have destructors and "you'll learn
    that when you've taking the same courses in school like myself, son"?

    The exception throw/catch-talk however, was relevant, thank you for that.

    I don't see many explations to the static destructor-thing yet...
     
    someone, Dec 31, 2011
    #6
  7. someone

    MikeWhy Guest

    someone wrote:
    > On 12/31/2011 04:22 AM, MikeWhy wrote:
    >> someone wrote:
    >>> On 12/31/2011 03:06 AM, MikeWhy wrote:
    >>>> someone wrote:

    > ..
    >
    >>>>> If I enable (uncomment) middle line, I get:
    >>>>> Constructing Base
    >>>>> Constructing Derive
    >>>>> Destroying Derive
    >>>>> Destroying Base
    >>>>>
    >>>>>
    >>>>> If I disable (comment out) middle line, I get:
    >>>>> Constructing Base
    >>>>> Constructing Derive
    >>>>>
    >>>>>
    >>>>> ========
    >>>>>
    >>>>> This, I didn't quite expect, because I thought that at the end of
    >>>>> the program, all destructors where guaranteed to be called...
    >>>>
    >>>> If pointers had destructors, what action should they take?
    >>>
    >>> Delete themselves? But not before they've destructed the objects
    >>> they're pointing to! After they've destructed (free'd) the
    >>> dereferenced objects, the pointers can free themselves...
    >>>
    >>> Why doesn't that happen in the example in my post and in my full
    >>> code?

    >
    > No answer?


    Answered below in that message.

    >
    >>>>> In my case, I have a longer program and I allocate memory with one
    >>>>> of my constructors, hence it is crucial to free the memory, but
    >>>>> since the virtual destructor is never called, I never free the
    >>>>> memory... In addition: In my full program (not shown here), I
    >>>>> instantiate my
    >>>>> new object like:
    >>>>>
    >>>>> int main(...)
    >>>>> {
    >>>>> ...
    >>>>> Derive d1();
    >>>>> return 0; // or exit(1); if something went wrong somewhere
    >>>>> }
    >>>>>
    >>>>> Is it required that I do, like in the example above:
    >>>>>
    >>>>> int main(...)
    >>>>> {
    >>>>> ...
    >>>>> Base *myPtr = new Derive();
    >>>>
    >>>> foo(); // insert this line. See below.
    >>>>> delete myPtr;
    >>>>> return 0; // or exit(1); if something went wrong somewhere
    >>>>> }
    >>>>>
    >>>>> ???????
    >>>>
    >>>> Yes.
    >>>
    >>> Ok, but I don't understand why... I found this post:
    >>> http://www.tech-archive.net/Archive/VC/microsoft.public.vc.mfc/2007-05/msg01433.html
    >>>
    >>>
    >>> from where I qoute: "Static objects are deleted (so the destructor
    >>> is called) when global variables are deallocated, so when the
    >>> program exits."
    >>> I believe this code:
    >>>
    >>> int main(...)
    >>> {
    >>> ...
    >>> Derive d1();
    >>> return 0; // or exit(1); if something went wrong somewhere
    >>> }
    >>>
    >>> Has d1 to be a static object, hence when the program exits, the
    >>> destructor of d1 should be called just before exitting... Why don't
    >>> this happen?
    >>>
    >>>>> But what if my code does an exit(1) somewhere, which it could do
    >>>>> at least a dozens of times, in different parts of the program?
    >>>>
    >>>> exit() is a function call. In your final example above, if foo()
    >>>> called exit(1), will your destructor be called? Given what you saw
    >>>> earlier, how does exit() trigger process termination?
    >>>
    >>> exit() is not a normal function call. Normally, code execution
    >>> continues right after the function calls. But not with exit(). Code
    >>> below exit() is not executed.
    >>>
    >>>> If instead of calling exit(), foo() throws an uncaught exception.
    >>>> How does the program behave?
    >>>
    >>> I later found some posts on google, suggesting to throw/catch
    >>> exceptions, however I'm not very good at using exceptions and fear
    >>> that the code will be much more complicated.
    >>>
    >>>> Calling exit() is a very bad idea. Ditto for terminating threads,
    >>>> only more so. A simple return will suffice. Find some other
    >>>> mechanism to trigger process (and thread) termination.
    >>>
    >>> return() has exactly the same problem as exit: The code below
    >>> return() in main is not executed, hence I believe that exit() is
    >>> some kind of acronym for return() (from the main thread)...

    >>
    >> return is a C/C++ keyword. exit() is a function call. It kills the
    >> process and does not return. Since exit() doesn't return, foo()
    >> doesn't return. Since foo() doesn't return, execution will not
    >> continue in main(). Your delete will not be called.

    >
    > But it's not the answer to why, when I create static objects, the
    > destructor of d1 is not called when exitting... Right?
    >
    >> You're asking the right questions. You now need to understand the
    >> distinction.
    >>
    >> There also was a reason to bring up exceptions. The exception would
    >> have behaved as you thought exit() might. In the contexts you
    >> describe -- calling exit(1) in multiple locations -- the semantics
    >> and behavior are as you expected from exit().
    >>
    >>
    >>> Anyway, please explain why the static destructor is not called on
    >>> exit. I don't understand why not...

    >>
    >> The truth of the matter is that pointers do not have destructors. My
    >> intention was not to lead you astray, however. You'll visit this
    >> again in shared_ptr and auto_ptr classes.

    >
    > So you don't want to explain it?


    I'll go so far as to say that pointers -- along with int, char, and arrays
    as further examples -- do not have destructors. Plain old data, POD, as
    opposed to classes and structs. To say more would needlessly repeat
    countless books, articles, blogs, and archived usenet and chatboard
    postings. From your well reasoned earlier post, it did seem to me all you
    needed was a well directed nudge.

    To answer your question, then... What would happen in your first example,
    where you passed an int* to a function, if pointers had the behavior of
    deleting their pointee in their hypothetical destructor?

    I am still of the opinion that you need only a nudge, not a silver spoon. If
    that wasn't the case, I assure you I would not be spending my time.


    > FYI: I have no shared_ptr and auto_ptr classes, I don't know what it
    > means and I'll never take them. I'm too old for that. You're not that
    > old yourself and hence assumed that everyone in here is a student,
    > doing school work? Never heard of something like: Went out of school
    > years ago, but am learning a new programming language anyway?
    >
    > I don't understand why you not just explain it, instead of all this
    > irrelevant talk about if pointers have destructors and "you'll learn
    > that when you've taking the same courses in school like myself, son"?
    >
    > The exception throw/catch-talk however, was relevant, thank you for
    > that.
    > I don't see many explations to the static destructor-thing yet...


    It would please me if the explanation came next from you. It's entirely
    likely, or at least possible, that I've been out of school as long as you.
     
    MikeWhy, Dec 31, 2011
    #7
  8. someone

    someone Guest

    On 12/31/2011 04:50 AM, Garrett Hartshaw wrote:
    > On Sat, 31 Dec 2011 02:43:28 +0100, someone <> wrote:
    >> Hi


    >> Please advice, thank you!

    >
    > A statically constructed object will be destroyed when the scope is left.
    >
    > e.g destructors will be called in:
    > int main()
    > {
    > Derived d;
    > return 0;
    > }


    Ah, stupid me. I thought I had tried the above, and that it didn't work
    - thank you very much. My mistake, maybe also in reply to MikeWhy...

    > A dynamically constructed object (created using new) is destroyed when
    > delete is called.
    >
    > e.g destructors called in this:
    > int main()
    > {
    > Base * b = new Derived();
    > delete b;
    > return 0;
    > }
    >
    > but not this:
    > int main()
    > {
    > Base * b = new Derived();
    > return 0;
    > }
    >


    Yes, this is clear now, the static thing was a brain-something that hit
    me...

    > When exit(int) is called, the program is terminated *without unwinding
    > the stack* so no destructors are called.


    Yes, clear.

    > When a execption is thrown and not caught, the program is terminated
    > *with stack unwinding*, so static objects are destroyed.


    Aah, only static objects... DAMN...

    > Note: int main()
    > {
    > Base * b = new Derived();
    > throw std::exception();
    > delete b;
    > return 0;
    > }
    >
    > In the above, the delete expression is never reached, so destructors are
    > not called.


    That is a big problem/issue in my program, I think...

    So if I allocate memory in my constructor, and I never call the
    destructor and I keep running and exiting, running and exiting the
    program, then I end up using all my memory because I never free'd it?

    > If this is an issue, a smart pointer (boost::shared_ptr,
    > boost::scoped_ptr, etc:) should be used.


    Ooh, damn...

    I hoped, I could avoid having to learn something new and timeconsuming
    like boost...

    Isn't there an easier solution without including more libraries?


    Thank you very much, by the way!
     
    someone, Dec 31, 2011
    #8
  9. someone

    MikeWhy Guest

    MikeWhy wrote:
    > someone wrote:
    >> FYI: I have no shared_ptr and auto_ptr classes, I don't know what it
    >> means and I'll never take them. I'm too old for that. You're not that
    >> old yourself and hence assumed that everyone in here is a student,
    >> doing school work? Never heard of something like: Went out of school
    >> years ago, but am learning a new programming language anyway?



    Hmmm...

    #include <memory>

    You may discount my earlier post. I had not understood our communications to
    have been so severely crossed.
     
    MikeWhy, Dec 31, 2011
    #9
  10. someone

    someone Guest

    On 12/31/2011 05:28 AM, MikeWhy wrote:
    > someone wrote:
    >> FYI: I have no shared_ptr and auto_ptr classes, I don't know what it


    Are these shared_ptr and auto_ptr relevant for solving the problem? I
    googled it, but not sure if they solve anything...

    >> means and I'll never take them. I'm too old for that. You're not that
    >> old yourself and hence assumed that everyone in here is a student,
    >> doing school work? Never heard of something like: Went out of school
    >> years ago, but am learning a new programming language anyway?
    >>
    >> I don't understand why you not just explain it, instead of all this
    >> irrelevant talk about if pointers have destructors and "you'll learn
    >> that when you've taking the same courses in school like myself, son"?
    >>
    >> The exception throw/catch-talk however, was relevant, thank you for
    >> that.
    >> I don't see many explations to the static destructor-thing yet...

    >
    > It would please me if the explanation came next from you. It's entirely
    > likely, or at least possible, that I've been out of school as long as you.


    Ok, good. Thank you very much.

    I made a mistake, that confused me - I thought that the static
    destructor wasn't called, when main() returned with a 0... It confused
    me, don't know where I got that from...

    Everything is ok, I asked some questions to Garret about how to fix my
    problem now, hopefully without using boost::shared_ptr,
    boost::scoped_ptr, etc.

    hmmmmmmmmmmmmmmmmmm. Maybe a quick solution is to #define a macro
    exit(num), that does try and catch everytime I risk the program
    otherwise would be calling exit(1) etc... hmmmmmmmmmmmmm....
     
    someone, Dec 31, 2011
    #10
  11. someone

    MikeWhy Guest

    someone wrote:
    > On 12/31/2011 05:28 AM, MikeWhy wrote:
    >> someone wrote:
    >>> FYI: I have no shared_ptr and auto_ptr classes, I don't know what it

    >
    > Are these shared_ptr and auto_ptr relevant for solving the problem? I
    > googled it, but not sure if they solve anything...


    They don't directly address your problem. Strictly speaking, I felt the
    problem was not simply that delete was not being called. The problem
    entirely was that execution did not flow as you expected. auto_ptr was
    relevant because it makes real that hypothetical deletion behavior
    mentioned.

    >
    > hmmmmmmmmmmmmmmmmmm. Maybe a quick solution is to #define a macro
    > exit(num), that does try and catch everytime I risk the program
    > otherwise would be calling exit(1) etc... hmmmmmmmmmmmmm....


    It might be a good way to finish out your test program, which I understand
    to be a study of object lifetimes and program flow. I would not have chosen
    to introduce auto_ptr so early, but as it turns out, the role it plays is an
    important part of the broader topic of exception-safety.

    As a final note, hiding throw in a macro for exit is a bad idea. Blindly
    replacing exit(1) with throw(1) might not be altogether unreasonable,
    though.
     
    MikeWhy, Dec 31, 2011
    #11
  12. someone

    someone Guest

    On 12/31/2011 06:56 AM, MikeWhy wrote:
    > someone wrote:
    >> On 12/31/2011 05:28 AM, MikeWhy wrote:
    >>> someone wrote:


    >> hmmmmmmmmmmmmmmmmmm. Maybe a quick solution is to #define a macro
    >> exit(num), that does try and catch everytime I risk the program
    >> otherwise would be calling exit(1) etc... hmmmmmmmmmmmmm....

    >
    > It might be a good way to finish out your test program, which I
    > understand to be a study of object lifetimes and program flow. I would


    The test program is finished. It's posted here in the thread. The other
    program is a big complicated program, where I have to find a solution,
    to the problem where the destructor is not called, when exit(1) and/or
    exceptions are thrown...

    > not have chosen to introduce auto_ptr so early, but as it turns out, the
    > role it plays is an important part of the broader topic of
    > exception-safety.
    >
    > As a final note, hiding throw in a macro for exit is a bad idea. Blindly
    > replacing exit(1) with throw(1) might not be altogether unreasonable,
    > though.


    Still don't solve the cleanup ("delete" / "free"ing up used memory
    space) problem... Not sure what to do then...
     
    someone, Dec 31, 2011
    #12
  13. someone

    LR Guest

    someone wrote:
    > On 12/31/2011 04:50 AM, Garrett Hartshaw wrote:
    >> On Sat, 31 Dec 2011 02:43:28 +0100, someone <> wrote:


    >> Note: int main()
    >> {
    >> Base * b = new Derived();
    >> throw std::exception();
    >> delete b;
    >> return 0;
    >> }
    >>
    >> In the above, the delete expression is never reached, so destructors are
    >> not called.

    >
    > That is a big problem/issue in my program, I think...
    >
    > So if I allocate memory in my constructor, and I never call the
    > destructor and I keep running and exiting, running and exiting the
    > program, then I end up using all my memory because I never free'd it?


    May I ask why you're allocating memory? I mean why are you writing new
    explicitly in your code? What are you trying to do?
    >
    >> If this is an issue, a smart pointer (boost::shared_ptr,
    >> boost::scoped_ptr, etc:) should be used.

    >
    > Ooh, damn...
    >
    > I hoped, I could avoid having to learn something new and timeconsuming
    > like boost...
    >
    > Isn't there an easier solution without including more libraries?


    What compiler and version are you using? You may find what you need in
    a header that shipped with your compiler.
     
    LR, Dec 31, 2011
    #13
  14. someone

    someone Guest

    On 12/31/2011 07:07 AM, LR wrote:
    > someone wrote:
    >> On 12/31/2011 04:50 AM, Garrett Hartshaw wrote:
    >>> On Sat, 31 Dec 2011 02:43:28 +0100, someone<> wrote:

    >
    >>> Note: int main()
    >>> {
    >>> Base * b = new Derived();
    >>> throw std::exception();
    >>> delete b;
    >>> return 0;
    >>> }
    >>>
    >>> In the above, the delete expression is never reached, so destructors are
    >>> not called.

    >>
    >> That is a big problem/issue in my program, I think...
    >>
    >> So if I allocate memory in my constructor, and I never call the
    >> destructor and I keep running and exiting, running and exiting the
    >> program, then I end up using all my memory because I never free'd it?

    >
    > May I ask why you're allocating memory? I mean why are you writing new
    > explicitly in your code? What are you trying to do?


    Because:

    I have some graphical objects that should be displayed on the screen.
    When I instantiate these objects, I don't know how many coordinates
    there are. When I know it, I use new to allocate memory for x,y and
    z-coordinates. It's pretty lame, if I should not allocate memory
    dynamically... It's hard to believe, it is so cumbersome. It would also
    look bad if I separate the x,y and z-coordinates from the graphical
    objects themselves. And even that would not solve the
    call-the-destructor-problem to free memory.

    >>> If this is an issue, a smart pointer (boost::shared_ptr,
    >>> boost::scoped_ptr, etc:) should be used.

    >>
    >> Ooh, damn...
    >>
    >> I hoped, I could avoid having to learn something new and timeconsuming
    >> like boost...
    >>
    >> Isn't there an easier solution without including more libraries?

    >
    > What compiler and version are you using? You may find what you need in
    > a header that shipped with your compiler.


    1) g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
    Copyright (C) 2011 Free Software Foundation, Inc.

    and

    2) Visual studio 2011

    = (crossplatform)
     
    someone, Dec 31, 2011
    #14
  15. someone <> wrote:
    > This, I didn't quite expect, because I thought that at the end of the
    > program, all destructors where guaranteed to be called...


    C++ does not implement garbage collection, which means that if you
    allocate an object dynamically with 'new', you'll have to destroy it
    explicitly with 'delete'. (Yes, I know that sucks, but either live with
    it or switch to C#.)

    If you want the dynamically allocated object to be destroyed automatically
    you'll have to use a smart pointer like std::shared_ptr to handle it. In
    most cases, though, it's better to avoid the 'new' if you can, and instead
    handle objects by value. When an object is handled by value it will be
    scope-bound, and thus will be destroyed when its scope ends. In surprisingly
    many cases (especially to people accustomed to languages like Java or C#),
    you don't need 'new' to handle objects.
     
    Juha Nieminen, Dec 31, 2011
    #15
  16. On Dec 31, 6:07 am, someone <> wrote:
    > On 12/31/2011 06:56 AM, MikeWhy wrote:
    > > someone wrote:



    > >> hmmmmmmmmmmmmmmmmmm. Maybe a quick solution is to #define a macro
    > >> exit(num), that does try and catch everytime I risk the program
    > >> otherwise would be calling exit(1) etc... hmmmmmmmmmmmmm....


    not sure exactlywhat you're up to here. But

    - hiding standard libraries behind macros seems like a bad idea.
    For a start it makes reading your code very difficult for other
    people.

    - what do you mean "a macro [...] that catches everything"?
    (slightly paraphrashing you)

    As the other poster said calling exit() in a C++ is generally a bad
    idea. It certainly precludes destrutors being called. I think the
    effect you want could be had by throwing and not catching. This will
    bubble all the way upto the top of the program, calling all the
    relevent DTORs on the way. Then exiting.

    > > It might be a good way to finish out your test program, which I
    > > understand to be a study of object lifetimes and program flow. I would

    >
    > The test program is finished. It's posted here in the thread. The other
    > program is a big complicated program, where I have to find a solution,
    > to the problem where the destructor is not called, when exit(1) and/or
    > exceptions are thrown...


    there's something seriuslywrong if they aren't being called when
    exceptions are thown!

    > > not have chosen to introduce auto_ptr so early, but as it turns out, the
    > > role it plays is an important part of the broader topic of
    > > exception-safety.

    >
    > > As a final note, hiding throw in a macro for exit is a bad idea. Blindly
    > > replacing exit(1) with throw(1) might not be altogether unreasonable,
    > > though.

    >
    > Still don't solve the cleanup ("delete" / "free"ing up used memory
    > space) problem... Not sure what to do then...


    post a simple, working program that illustrates your problem.
     
    Nick Keighley, Dec 31, 2011
    #16
  17. On Dec 31, 4:37 am, someone <> wrote:
    > On 12/31/2011 04:50 AM, Garrett Hartshaw wrote:
    >
    > > On Sat, 31 Dec 2011 02:43:28 +0100, someone <> wrote:
    > >> Hi
    > >> Please advice, thank you!

    >
    > > A statically constructed object will be destroyed when the scope is left.

    >
    > > e.g destructors will be called in:
    > > int main()
    > > {
    > > Derived d;
    > > return 0;
    > > }

    >
    > Ah, stupid me. I thought I had tried the above, and that it didn't work
    > - thank you very much. My mistake, maybe also in reply to MikeWhy...
    >
    >
    >
    >
    >
    > > A dynamically constructed object (created using new) is destroyed when
    > > delete is called.

    >
    > > e.g destructors called in this:
    > > int main()
    > > {
    > > Base * b = new Derived();
    > > delete b;
    > > return 0;
    > > }

    >
    > > but not this:
    > > int main()
    > > {
    > > Base * b = new Derived();
    > > return 0;
    > > }

    >
    > Yes, this is clear now, the static thing was a brain-something that hit
    > me...
    >
    > > When exit(int) is called, the program is terminated *without unwinding
    > > the stack* so no destructors are called.

    >
    > Yes, clear.
    >
    > > When a execption is thrown and not caught, the program is terminated
    > > *with stack unwinding*, so static objects are destroyed.

    >
    > Aah, only static objects... DAMN...
    >
    > > Note: int main()
    > > {
    > > Base * b = new Derived();
    > > throw std::exception();
    > > delete b;
    > > return 0;
    > > }

    >
    > > In the above, the delete expression is never reached, so destructors are
    > > not called.

    >
    > That is a big problem/issue in my program, I think...
    >
    > So if I allocate memory in my constructor, and I never call the
    > destructor and I keep running and exiting, running and exiting the
    > program, then I end up using all my memory because I never free'd it?
    >
    > > If this is an issue, a smart pointer (boost::shared_ptr,
    > > boost::scoped_ptr, etc:) should be used.

    >
    > Ooh, damn...
    >
    > I hoped, I could avoid having to learn something new and timeconsuming
    > like boost...
    >
    > Isn't there an easier solution without including more libraries?


    std::auto_ptr

    though I believe this is now deprecated. Hasn't been removed though
    and does the job.
     
    Nick Keighley, Dec 31, 2011
    #17
  18. On Dec 31, 7:54 am, someone <> wrote:
    > On 12/31/2011 07:07 AM, LR wrote:


    <snip>

    > > May I ask why you're allocating memory?  I mean why are you writing new
    > > explicitly in your code? What are you trying to do?

    >
    > Because:
    >
    > I have some graphical objects that should be displayed on the screen.
    > When I instantiate these objects, I don't know how many coordinates
    > there are. When I know it, I use new to allocate memory for x,y and
    > z-coordinates. It's pretty lame, if I should not allocate memory
    > dynamically... It's hard to believe, it is so cumbersome.


    would std::vector solve your problem? Something like this:-

    // vec.cpp

    #include <vector>

    struct Point
    {
    int x;
    int y;
    int z;
    };

    void draw (std::vector<Point>& graphicalObject)
    {
    // do whatever has to be done to draw the object
    }

    // make an object with pointCount points
    void makeObject (int pointCount)
    {
    std::vector<Point> graphicalObject(pointCount);
    // initialise it somehow
    draw (graphicalObject);
    // graphicalObject and all its points destroyed here
    }

    int main ()
    {
    int n = 10; // determine number of points somehow
    makeObject (n);
    }

    <snip>
     
    Nick Keighley, Dec 31, 2011
    #18
  19. someone

    Bo Persson Guest

    someone wrote:
    >
    > ========
    >
    > This, I didn't quite expect, because I thought that at the end of
    > the program, all destructors where guaranteed to be called...
    >
    > In my case, I have a longer program and I allocate memory with one
    > of my constructors, hence it is crucial to free the memory, but
    > since the virtual destructor is never called, I never free the
    > memory...
    > In addition: In my full program (not shown here), I instantiate my
    > new object like:
    >
    > int main(...)
    > {
    > ...
    > Derived d1();
    > return 0; // or exit(1); if something went wrong somewhere
    > }
    >


    This actually doesn't create an object, but declares a function d1
    that returns a Derived object. If you compare

    Derived d1();

    to the more common

    int f();

    you will see the similarity!


    Bo Persson
     
    Bo Persson, Dec 31, 2011
    #19
  20. someone

    Bo Persson Guest

    someone wrote:
    > On 12/31/2011 03:06 AM, MikeWhy wrote:
    >>
    >> If pointers had destructors, what action should they take?

    >
    > Delete themselves? But not before they've destructed the objects
    > they're pointing to! After they've destructed (free'd) the
    > dereferenced objects, the pointers can free themselves...
    >
    > Why doesn't that happen in the example in my post and in my full
    > code?


    There are several reasons. One is that pointers are inherited from the
    C language, and are expected to behave the same as they did there. In
    C there are no destructors at all.

    Another reason is that there can be several pointers pointing to the
    same object. How are they supposed to know which one should delete the
    object pointed to? Or if anyone should do that. Not all pointed-to
    objects are created by new.

    {
    int i = 0;
    int* p = &i;
    }

    Here we should definitely *not* call delete p.


    Bo Persson
     
    Bo Persson, Dec 31, 2011
    #20
    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. Rajesh.Rapaka

    freeing memory

    Rajesh.Rapaka, Apr 20, 2005, in forum: Java
    Replies:
    17
    Views:
    2,870
    Eric Sosman
    Apr 21, 2005
  2. Harald Kirsch

    freeing memory

    Harald Kirsch, Apr 22, 2005, in forum: Java
    Replies:
    0
    Views:
    458
    Harald Kirsch
    Apr 22, 2005
  3. Hassan Iqbal
    Replies:
    3
    Views:
    513
    Al Bowers
    Sep 25, 2003
  4. freeing memory....partially

    , Oct 4, 2003, in forum: C Programming
    Replies:
    12
    Views:
    586
  5. Rodrigo Dominguez

    memory allocation and freeing memory

    Rodrigo Dominguez, Jun 13, 2005, in forum: C Programming
    Replies:
    11
    Views:
    632
    Jean-Claude Arbaut
    Jun 15, 2005
Loading...

Share This Page