Bug 44952 - #include <iostream> implies global constructor.
Summary: #include <iostream> implies global constructor.
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 4.6.0
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-07-15 15:51 UTC by Jan Hubicka
Modified: 2010-12-14 18:50 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jan Hubicka 2010-07-15 15:51:43 UTC
Noticed while reading http://comments.gmane.org/gmane.comp.web.chromium.devel/16789

evans:/abuild/jh/trunk-install/bin/:[0]# more g.C
#include <iostream>
evans:/abuild/jh/trunk-install/bin/:[0]# ./g++  -O2 g.C -S
evans:/abuild/jh/trunk-install/bin/:[0]# more g.s
        .file   "g.C"
        .text
        .p2align 4,,15
        .type   _GLOBAL__I_g.C, @function
_GLOBAL__I_g.C:
.LFB969:
        .cfi_startproc
        subq    $8, %rsp
        .cfi_def_cfa_offset 16
        movl    $_ZStL8__ioinit, %edi
        call    _ZNSt8ios_base4InitC1Ev
        movl    $__dso_handle, %edx
        movl    $_ZStL8__ioinit, %esi
        movl    $_ZNSt8ios_base4InitD1Ev, %edi
        addq    $8, %rsp
        .cfi_def_cfa_offset 8
        jmp     __cxa_atexit
        .cfi_endproc
.LFE969:
Comment 1 pinskia@gmail.com 2010-07-15 16:02:32 UTC
Subject: Re:   New: #include <iostream.h> imply global constructor.

This is expected and iirc required by the c++ standard too.

On Jul 15, 2010, at 8:51 AM, "hubicka at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org 
 > wrote:

> Noticed while reading
> http://comments.gmane.org/gmane.comp.web.chromium.devel/16789
>
> evans:/abuild/jh/trunk-install/bin/:[0]# more g.C
> #include <iostream>
> evans:/abuild/jh/trunk-install/bin/:[0]# ./g++  -O2 g.C -S
> evans:/abuild/jh/trunk-install/bin/:[0]# more g.s
>        .file   "g.C"
>        .text
>        .p2align 4,,15
>        .type   _GLOBAL__I_g.C, @function
> _GLOBAL__I_g.C:
> .LFB969:
>        .cfi_startproc
>        subq    $8, %rsp
>        .cfi_def_cfa_offset 16
>        movl    $_ZStL8__ioinit, %edi
>        call    _ZNSt8ios_base4InitC1Ev
>        movl    $__dso_handle, %edx
>        movl    $_ZStL8__ioinit, %esi
>        movl    $_ZNSt8ios_base4InitD1Ev, %edi
>        addq    $8, %rsp
>        .cfi_def_cfa_offset 8
>        jmp     __cxa_atexit
>        .cfi_endproc
> .LFE969:
>
>
> -- 
>           Summary: #include <iostream.h> imply global constructor.
>           Product: gcc
>           Version: 4.6.0
>            Status: UNCONFIRMED
>          Severity: normal
>          Priority: P3
>         Component: libstdc++
>        AssignedTo: unassigned at gcc dot gnu dot org
>        ReportedBy: hubicka at gcc dot gnu dot org
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44952
>
Comment 2 Richard Biener 2010-07-15 16:03:55 UTC
Why's this not in libstdc++.so .init?
Comment 3 Jan Hubicka 2010-07-15 16:12:27 UTC
... and are we required to emit the constructor even if we know var is not used?
Comment 4 Andrew Pinski 2010-07-15 16:30:23 UTC
(In reply to comment #2)
> Why's this not in libstdc++.so .init?

because this will not work if libstdc++ is a static library.
Take:

#include <iostream>

namespace {
struct g
{
  g(){ std::cout << "t"; }
};
g one;
}

--- CUT ---
The C++ standard says order of initializers between TUs is unspecified (though the order inside TUs is specified as being the first one will run first).
So with a static version, the above will be included first and that will cause std::cout to be used without being initialized.

>... and are we required to emit the constructor even if we know var is not
used?
It is hard to do that in Standard C++ really or imposable.
Comment 5 Jonathan Wakely 2010-07-15 16:38:52 UTC
This is why you should only include <iostream> if you want actually want std::cin, std::cout or std::cerr (or the wide character equivalents.)
Otherwise you should only include one or more of <iosfwd>, <istream> and <ostream>, as needed.


(In reply to comment #3)
> ... and are we required to emit the constructor even if we know var is not
> used?

27.4 [iostream.objects] paragraph 2
The results of including <iostream> in a translation unit shall be as if <iostream> defined an instance of ios_base::Init with static storage
duration. Similarly, the entire program shall behave as if there were at least one instance of ios_base::Init with static storage duration.




Comment 6 Jonathan Wakely 2010-07-15 16:45:13 UTC
and please ... it's 2010, <iostream> not <iostream.h>  ;-)

Comment 7 Jan Hubicka 2010-07-15 16:53:15 UTC
Hehe, I am really not C++ guy even in 2010, but I have impression that people are including iostream without really thinking about consequences here.

Well, so what we can do about the startup times then?  I will teach ipa-profile to propagate info if function is only called from constructor and will put them into separate section. This will save the random access at file startup. But we ought to be able to do better.
Comment 8 Jonathan Wakely 2010-07-15 17:49:15 UTC
(In reply to comment #7)
> Hehe, I am really not C++ guy even in 2010, but I have impression that people
> are including iostream without really thinking about consequences here.

Yes, and in many cases that's the simplest thing to do, but it has a cost.
 
> Well, so what we can do about the startup times then?

I would do nothing.  If people care about startup times they should not include facilities they don't use.



Comment 9 Paolo Carlini 2010-07-15 18:26:09 UTC
Let's say we remove that horrible .h from the Summary, since, to be fair, didn't exist in g.C in the first place ;)

That said, I agree with Jon, by and large, with the following minor additional observations: 1- I'm pretty sure the library is correct, but we should double check whether other established and new implementations of the C++ runtime are trying to do something special, performance-wise - low priority I'm afraid; 2- As library maintainers we certainly welcome any improvement to the optimizers improving the code GCC generates for these constructors, because certainly many user applications could benefit, not just because the library would; -3 While we are at it, I think we should make sure not regressing on libstdc++/39796, or even making progress at once. Ideas? (I didn't really manage to study it in any detail)
Comment 10 Andrew Pinski 2010-07-22 00:01:53 UTC
The C++ standard actually requires this as noted in comment #5.
Comment 11 Jakub Jelinek 2010-07-22 11:03:48 UTC
Perhaps with LTO we could special case this (perhaps using some special attribute) and only construct/destruct the first of these
  static ios_base::Init __ioinit;
vars and optimize all the others away together with their construction/destruction, assuming they aren't otherwise referenced.
Comment 12 Paolo Carlini 2010-07-22 11:25:41 UTC
The same idea vaguely occurred to me...
Comment 13 Jakub Jelinek 2010-07-22 11:41:29 UTC
So reopening for this enhancement...

Another alternative would be some .init.first array or something similar which would contain pointers to functions to be run as early constructors and linker would remove duplicates in it and put it at the beginning of .init_array section.
Comment 14 Jan Hubicka 2010-08-19 09:39:14 UTC
Well, it might be easy to modify libstdc++ implementation so the static constructor compiles into single function call.  Then we can teach GCC to optimize constructor containing only a call into entry in ctors table.
Then we will get a lot of duplicate calls, but all at one place and we won't have the locality problem at startup.
Comment 15 Cary Coutant 2010-12-14 18:50:11 UTC
(In reply to comment #13)
> So reopening for this enhancement...
> 
> Another alternative would be some .init.first array or something similar which
> would contain pointers to functions to be run as early constructors and linker
> would remove duplicates in it and put it at the beginning of .init_array
> section.

For ELF targets, this is what DT_PREINIT_ARRAY is for.

http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#init_fini

-cary