Topic: destruction of global/namespace objects


Author: "Ron Ruble" <raffles1@worldnet.att.net>
Date: 1997/09/02
Raw View
Craig Perras wrote in article ...

>I am confused on how namespace variables destruct. Here's the situation:
<SNIP>
>namespace MyNamespace {
>   Manager manager;
>   Manager::Manager() {
>      std::cout << "Constructing Manager!" << std::endl;
>   }
>   Manager::~Manager() {
>      std::cout << "Deleting Manager!" << std::endl;
>   }
>};
<SNIP>
>In the above case, it seems cout would have to be valid, else I would
>think it should just crash.
<SNIP>
>Any clues on the expected behaviour? BTW - I am using MSVC 5.0, in case
>that matters.

I think we need a ruling from an expert language lawyer, but I think this
code falls under the 'implementation defined' category.

Debugging into this code shows that the destructor is being called; you can
see this by adding a printf() call after the cout line. For why this occurs,
my copy of the draft states that objects declared within specific namespaces
will be destroyed 'in the reverse order of their constructor calls -or- the
reverse order of the completion of their dynamic initialization'. It also
states that the order of dynamic initialization is implementation defined,
and is not guaranted to be complete until the object is used.

I suspect that VC++ initializes cout only when it is used, and that while
cout is still a valid object, the output stream it maps to isn't. In Windows
console output is a special case of the GUI interface.

The reason an exception isn't thrown is because cout still exists, and is a
valid object; however, its member good(), bad() and fail() functions
indicate that it isn't connected to a valid output stream anymore (again,
you can see this with printf()). Because of this, you can still call its >>
operator, but it fails to display anything.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Craig Perras <craigp@wolfenet.COM>
Date: 1997/09/08
Raw View

On 2 Sep 1997, Ron Ruble wrote:

 > Craig Perras wrote in article ...
 >
 > >I am confused on how namespace variables destruct. Here's the situation:
 > <SNIP>
 > >namespace MyNamespace {
 > >   Manager manager;
 > >   Manager::Manager() {
 > >      std::cout << "Constructing Manager!" << std::endl;
 > >   }
 > >   Manager::~Manager() {
 > >      std::cout << "Deleting Manager!" << std::endl;
 > >   }
 > >};

<SNIP>

 > Debugging into this code shows that the destructor is being called; you can
 > see this by adding a printf() call after the cout line. For why this occurs,
 > my copy of the draft states that objects declared within specific namespaces
 > will be destroyed 'in the reverse order of their constructor calls -or- the
 > reverse order of the completion of their dynamic initialization'. It also
 > states that the order of dynamic initialization is implementation defined,
 > and is not guaranted to be complete until the object is used.

It is surprising (to me, anyway) that cout (along with it's streambuf) is
constructed before manager (as demonstrated by the program's output), yet
is destructed first. In general, I would expect it to follow the familiar
pattern of 'first constructed, last destroyed' - even in the case of
global variables.

in this particular case, cout is used in manager's constructor, so I would
(naively?) think that cout and it's streambuf are initialized before
manager, which then suggests cout should be destructed last.

--craig
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Steve Clamage <stephen.clamage_nospam@Eng.Sun.COM>
Date: 1997/09/08
Raw View

Craig Perras wrote:
>
> I am confused on how namespace variables destruct. Here's the situation:

[ destructor for namespace-scope object writes to std::cout but no
  output appears. ]

> The obvious question is where is 'Deleting Manager!'? I stepped thru this
> with a debugger, and Manager::~Manager() appears to be executing ok - it
> simply doesn't output to the screen. Is there a rule which dictates that
> cout must exist until manager destructs?

Yes. Draft standard section 27.3 "Standard iostream objects" says in
effect that destructors for static objects can use the standard
streams, and the streams must not be destroyed before those
static objects. This assumes that the <iostream> header was included
in the translation unit ahead of the definition of such a static
object, which is the case in your example. Classic iostreams had the
same requirement.

It looks like the implementor neglected to ensure that cout sticks
around
long enough.

--
Steve Clamage, stephen.clamage_nospam@eng.sun.com
( Note: remove "_nospam" when replying )
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Craig Perras <craigp@wolfenet.COM>
Date: 1997/08/29
Raw View
I am confused on how namespace variables destruct. Here's the situation:

in file mgr.h:


#include <iostream>

class Manager {
public:
 Manager();
 ~Manager();
};


in mgr.cpp:


#include "mgr.h"

namespace MyNamespace {

   Manager manager;

   Manager::Manager() {
      std::cout << "Constructing Manager!" << std::endl;
   }

   Manager::~Manager() {
      std::cout << "Deleting Manager!" << std::endl;
   }

};



and in main.cpp:


void main() {
 std::cout << "in main" << std::endl;
}


When I compile and run this, the output is (you guessed it!):


Constructing Manager!
in main


The obvious question is where is 'Deleting Manager!'? I stepped thru this
with a debugger, and Manager::~Manager() appears to be executing ok - it
simply doesn't output to the screen. Is there a rule which dictates that
cout must exist until manager destructs? I know globals in different
translation units do not have any defined order in which they are
constructed, but is this equally valid for when they are destructed?

In the above case, it seems cout would have to be valid, else I would
think it should just crash.

Any clues on the expected behaviour? BTW - I am using MSVC 5.0, in case
that matters.

--craig
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]