[libcxx] Why the type of (w)cin/(w)cout/(w)cout are char []?

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

[libcxx] Why the type of (w)cin/(w)cout/(w)cout are char []?

Neil Nelson via cfe-dev
Hello all,

I am porting libcxx to Windows (not mingw). I am curious about the design of (w)cin/(w)cout/(w)cout. Currently we define (w)cin/(w)cout/(w)cout as char[] under src/iostream.cpp and initialise them as istream/ostream in function ios_base::Init::Init(). Why don't we defined them as istream/ostream object directly? The drawback of current design in my mind is that cause linking error under Windows. Windows mangler takes data type into account. Reference of std::cin would be translated into ?cin@__1@std@@3V?$basic_istream@DU?$char_traits@D@__1@std@@@12@A (class std::__1::basic_istream<char,struct std::__1::char_traits<char> > std::__1::cin). Definition of std::cin, in contrast, would be translated into ?cin@__1@std@@3PADA (char * std::__1::cin). There is a linking error because two symbols are different.

Any suggestion or comment is appreciated,
Yi-Hong

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [libcxx] Why the type of (w)cin/(w)cout/(w)cout are char []?

Neil Nelson via cfe-dev


On 5/16/16 12:12 PM, Yi-Hong Lyu via cfe-dev wrote:
> Hello all,
>
> I am porting libcxx to Windows (not mingw). I am curious about the
> design of (w)cin/(w)cout/(w)cout. Currently we define
> (w)cin/(w)cout/(w)cout as char[] under src/iostream.cpp and initialise
> them as istream/ostream in function ios_base::Init::Init(). Why don't we
> defined them as istream/ostream object directly?

I /think/ the reasoning behind this is to get tight control over their
initialization order.


Jon

> The drawback of current
> design in my mind is that cause linking error under Windows. Windows
> mangler takes data type into account. Reference of std::cin would be
> translated into
> ?cin@__1@std@@3V?$basic_istream@DU?$char_traits@D@__1@std@@@12@A (class
> std::__1::basic_istream<char,struct std::__1::char_traits<char> >
> std::__1::cin). Definition of std::cin, in contrast, would be translated
> into ?cin@__1@std@@3PADA (char * std::__1::cin). There is a linking
> error because two symbols are different.
>
> Any suggestion or comment is appreciated,
> Yi-Hong
>
>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>

--
Jon Roelofs
[hidden email]
CodeSourcery / Mentor Embedded
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [libcxx] Why the type of (w)cin/(w)cout/(w)cout are char []?

Neil Nelson via cfe-dev
In reply to this post by Neil Nelson via cfe-dev
On May 16, 2016, at 2:12 PM, Yi-Hong Lyu via cfe-dev <[hidden email]> wrote:
>
> Hello all,
>
> I am porting libcxx to Windows (not mingw). I am curious about the design of (w)cin/(w)cout/(w)cout. Currently we define (w)cin/(w)cout/(w)cout as char[] under src/iostream.cpp and initialise them as istream/ostream in function ios_base::Init::Init(). Why don't we defined them as istream/ostream object directly? The drawback of current design in my mind is that cause linking error under Windows. Windows mangler takes data type into account. Reference of std::cin would be translated into ?cin@__1@std@@3V?$basic_istream@DU?$char_traits@D@__1@std@@@12@A (class std::__1::basic_istream<char,struct std::__1::char_traits<char> > std::__1::cin). Definition of std::cin, in contrast, would be translated into ?cin@__1@std@@3PADA (char * std::__1::cin). There is a linking error because two symbols are different.
>
> Any suggestion or comment is appreciated,

This was done because the standard forbids the destruction of these objects in the atexit chain.

Howard



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

signature.asc (817 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [libcxx] Why the type of (w)cin/(w)cout/(w)cout are char []?

Neil Nelson via cfe-dev
Hello Jon & Howard,

Thanks for your reply. I took a look of C++ specification. It mentioned constructors and destructors for static objects can access these objects (cin/cout/cerr) to read input from stdin or write output to stdout or stderr. As far as I know, cin/cout/cerr is initialized by the constructor of __start_std_streams under src/iostream.cpp. I am wondering how libcxx guarantee ios_base::Init::Init() would be invoked before execution of constructor of any other static objects? Is there any potential 'static initialization order fiasco' issue?

Thanks for your help,
Yi-Hong

2016-05-17 3:54 GMT+08:00 Howard Hinnant via cfe-dev <[hidden email]>:
On May 16, 2016, at 2:12 PM, Yi-Hong Lyu via cfe-dev <[hidden email]> wrote:
>
> Hello all,
>
> I am porting libcxx to Windows (not mingw). I am curious about the design of (w)cin/(w)cout/(w)cout. Currently we define (w)cin/(w)cout/(w)cout as char[] under src/iostream.cpp and initialise them as istream/ostream in function ios_base::Init::Init(). Why don't we defined them as istream/ostream object directly? The drawback of current design in my mind is that cause linking error under Windows. Windows mangler takes data type into account. Reference of std::cin would be translated into ?cin@__1@std@@3V?$basic_istream@DU?$char_traits@D@__1@std@@@12@A (class std::__1::basic_istream<char,struct std::__1::char_traits<char> > std::__1::cin). Definition of std::cin, in contrast, would be translated into ?cin@__1@std@@3PADA (char * std::__1::cin). There is a linking error because two symbols are different.
>
> Any suggestion or comment is appreciated,

This was done because the standard forbids the destruction of these objects in the atexit chain.

Howard



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [libcxx] Why the type of (w)cin/(w)cout/(w)cout are char []?

Neil Nelson via cfe-dev
It has been a long time since I wrote this code, but at the time I was able to convince myself that the libc++ initialization of global statics would happen prior other statics programmed by the customer.  At that time, libc++ was being written just for OS X.

Howard

On May 16, 2016, at 6:02 PM, Yi-Hong Lyu <[hidden email]> wrote:

>
> Hello Jon & Howard,
>
> Thanks for your reply. I took a look of C++ specification. It mentioned constructors and destructors for static objects can access these objects (cin/cout/cerr) to read input from stdin or write output to stdout or stderr. As far as I know, cin/cout/cerr is initialized by the constructor of __start_std_streams under src/iostream.cpp. I am wondering how libcxx guarantee ios_base::Init::Init() would be invoked before execution of constructor of any other static objects? Is there any potential 'static initialization order fiasco' issue?
>
> Thanks for your help,
> Yi-Hong
>
> 2016-05-17 3:54 GMT+08:00 Howard Hinnant via cfe-dev <[hidden email]>:
> On May 16, 2016, at 2:12 PM, Yi-Hong Lyu via cfe-dev <[hidden email]> wrote:
> >
> > Hello all,
> >
> > I am porting libcxx to Windows (not mingw). I am curious about the design of (w)cin/(w)cout/(w)cout. Currently we define (w)cin/(w)cout/(w)cout as char[] under src/iostream.cpp and initialise them as istream/ostream in function ios_base::Init::Init(). Why don't we defined them as istream/ostream object directly? The drawback of current design in my mind is that cause linking error under Windows. Windows mangler takes data type into account. Reference of std::cin would be translated into ?cin@__1@std@@3V?$basic_istream@DU?$char_traits@D@__1@std@@@12@A (class std::__1::basic_istream<char,struct std::__1::char_traits<char> > std::__1::cin). Definition of std::cin, in contrast, would be translated into ?cin@__1@std@@3PADA (char * std::__1::cin). There is a linking error because two symbols are different.
> >
> > Any suggestion or comment is appreciated,
>
> This was done because the standard forbids the destruction of these objects in the atexit chain.
>
> Howard
>
>
>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

signature.asc (817 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [libcxx] Why the type of (w)cin/(w)cout/(w)cout are char []?

Neil Nelson via cfe-dev


On Mon, May 16, 2016 at 4:15 PM, Howard Hinnant via cfe-dev <[hidden email]> wrote:
It has been a long time since I wrote this code, but at the time I was able to convince myself that the libc++ initialization of global statics would happen prior other statics programmed by the customer.  At that time, libc++ was being written just for OS X.


I don't think this holds any longer, including on OS X. I know it doesn't hold for things linked in statically (ie libc++experimental). However the alternative is to emit a static construction in every TU that include <iostream> (http://llvm.org/docs/CodingStandards.html#include-iostream-is-forbidden). I would be pretty unwilling to make that change until *not* doing it becomes a large issue.

One alternative to using char[] arrays to prevent destruction would be to use a C++11 union with an empty destructor. That could be a possible implementation for Windows.
 

Howard

On May 16, 2016, at 6:02 PM, Yi-Hong Lyu <[hidden email]> wrote:
>
> Hello Jon & Howard,
>
> Thanks for your reply. I took a look of C++ specification. It mentioned constructors and destructors for static objects can access these objects (cin/cout/cerr) to read input from stdin or write output to stdout or stderr. As far as I know, cin/cout/cerr is initialized by the constructor of __start_std_streams under src/iostream.cpp. I am wondering how libcxx guarantee ios_base::Init::Init() would be invoked before execution of constructor of any other static objects? Is there any potential 'static initialization order fiasco' issue?
>
> Thanks for your help,
> Yi-Hong
>
> 2016-05-17 3:54 GMT+08:00 Howard Hinnant via cfe-dev <[hidden email]>:
> On May 16, 2016, at 2:12 PM, Yi-Hong Lyu via cfe-dev <[hidden email]> wrote:
> >
> > Hello all,
> >
> > I am porting libcxx to Windows (not mingw). I am curious about the design of (w)cin/(w)cout/(w)cout. Currently we define (w)cin/(w)cout/(w)cout as char[] under src/iostream.cpp and initialise them as istream/ostream in function ios_base::Init::Init(). Why don't we defined them as istream/ostream object directly? The drawback of current design in my mind is that cause linking error under Windows. Windows mangler takes data type into account. Reference of std::cin would be translated into ?cin@__1@std@@3V?$basic_istream@DU?$char_traits@D@__1@std@@@12@A (class std::__1::basic_istream<char,struct std::__1::char_traits<char> > std::__1::cin). Definition of std::cin, in contrast, would be translated into ?cin@__1@std@@3PADA (char * std::__1::cin). There is a linking error because two symbols are different.
> >
> > Any suggestion or comment is appreciated,
>
> This was done because the standard forbids the destruction of these objects in the atexit chain.
>
> Howard
>
>
>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [libcxx] Why the type of (w)cin/(w)cout/(w)cout are char []?

Neil Nelson via cfe-dev
On May 16, 2016, at 9:58 PM, Eric Fiselier <[hidden email]> wrote:
>
>
>
> On Mon, May 16, 2016 at 4:15 PM, Howard Hinnant via cfe-dev <[hidden email]> wrote:
>> It has been a long time since I wrote this code, but at the time I was able to convince myself that the libc++ initialization of global statics would happen prior other statics programmed by the customer.  At that time, libc++ was being written just for OS X.
>>
>
> I don't think this holds any longer, including on OS X.

Interesting.

> I know it doesn't hold for things linked in statically (ie libc++experimental).

Agreed.  At the time I made this decision, I was consciously deciding that OS X would have only a dylib std::lib option.

> However the alternative is to emit a static construction in every TU that include <iostream> (http://llvm.org/docs/CodingStandards.html#include-iostream-is-forbidden). I would be pretty unwilling to make that change until *not* doing it becomes a large issue.

At the time, Apple was (and almost certainly still is) allergic to namespace scope statics requiring dynamic initialization.  By moving __start_std_streams into a source, as opposed to its traditional place in a header, I reduced the number of namespace scope statics associated with <iostream> from once per inclusion to only one for linking against the std::lib.  This was a deliberate design choice to deal with Apple’s allergies.

I have no strong opinion on if, when or where this design decision should be reversed.  I’m merely documenting the rationale that I used in case that is helpful.

>
> One alternative to using char[] arrays to prevent destruction would be to use a C++11 union with an empty destructor. That could be a possible implementation for Windows.

That sounds interesting.  Another option is a clean-sheet optimal implementation for each platform separated out with #if.  It isn’t that much code.

Howard

>
>
> Howard
>
> On May 16, 2016, at 6:02 PM, Yi-Hong Lyu <[hidden email]> wrote:
> >
> > Hello Jon & Howard,
> >
> > Thanks for your reply. I took a look of C++ specification. It mentioned constructors and destructors for static objects can access these objects (cin/cout/cerr) to read input from stdin or write output to stdout or stderr. As far as I know, cin/cout/cerr is initialized by the constructor of __start_std_streams under src/iostream.cpp. I am wondering how libcxx guarantee ios_base::Init::Init() would be invoked before execution of constructor of any other static objects? Is there any potential 'static initialization order fiasco' issue?
> >
> > Thanks for your help,
> > Yi-Hong
> >
> > 2016-05-17 3:54 GMT+08:00 Howard Hinnant via cfe-dev <[hidden email]>:
> > On May 16, 2016, at 2:12 PM, Yi-Hong Lyu via cfe-dev <[hidden email]> wrote:
> > >
> > > Hello all,
> > >
> > > I am porting libcxx to Windows (not mingw). I am curious about the design of (w)cin/(w)cout/(w)cout. Currently we define (w)cin/(w)cout/(w)cout as char[] under src/iostream.cpp and initialise them as istream/ostream in function ios_base::Init::Init(). Why don't we defined them as istream/ostream object directly? The drawback of current design in my mind is that cause linking error under Windows. Windows mangler takes data type into account. Reference of std::cin would be translated into ?cin@__1@std@@3V?$basic_istream@DU?$char_traits@D@__1@std@@@12@A (class std::__1::basic_istream<char,struct std::__1::char_traits<char> > std::__1::cin). Definition of std::cin, in contrast, would be translated into ?cin@__1@std@@3PADA (char * std::__1::cin). There is a linking error because two symbols are different.
> > >
> > > Any suggestion or comment is appreciated,
> >
> > This was done because the standard forbids the destruction of these objects in the atexit chain.
> >
> > Howard
> >
> >
> >
> > _______________________________________________
> > cfe-dev mailing list
> > [hidden email]
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
> >
> >
>
>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

signature.asc (817 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [libcxx] Why the type of (w)cin/(w)cout/(w)cout are char []?

Neil Nelson via cfe-dev


On Mon, May 16, 2016 at 8:13 PM, Howard Hinnant <[hidden email]> wrote:
On May 16, 2016, at 9:58 PM, Eric Fiselier <[hidden email]> wrote:
>
>
>
> On Mon, May 16, 2016 at 4:15 PM, Howard Hinnant via cfe-dev <[hidden email]> wrote:
>> It has been a long time since I wrote this code, but at the time I was able to convince myself that the libc++ initialization of global statics would happen prior other statics programmed by the customer.  At that time, libc++ was being written just for OS X.
>>
>
> I don't think this holds any longer, including on OS X.

Interesting.

Dropping the list. I probably should have been clearer. I haven't tested it yet, but I had static initialization order issues on OS X while writing the global PMRs. I just assumed the same issue may transfer to the std::stream case.
It's very possible I'm wrong and ignorant.

/Eric


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [libcxx] Why the type of (w)cin/(w)cout/(w)cout are char []?

Neil Nelson via cfe-dev
Dropping the list. 

Or not.

On Mon, May 16, 2016 at 8:15 PM, Eric Fiselier <[hidden email]> wrote:


On Mon, May 16, 2016 at 8:13 PM, Howard Hinnant <[hidden email]> wrote:
On May 16, 2016, at 9:58 PM, Eric Fiselier <[hidden email]> wrote:
>
>
>
> On Mon, May 16, 2016 at 4:15 PM, Howard Hinnant via cfe-dev <[hidden email]> wrote:
>> It has been a long time since I wrote this code, but at the time I was able to convince myself that the libc++ initialization of global statics would happen prior other statics programmed by the customer.  At that time, libc++ was being written just for OS X.
>>
>
> I don't think this holds any longer, including on OS X.

Interesting.

Dropping the list. I probably should have been clearer. I haven't tested it yet, but I had static initialization order issues on OS X while writing the global PMRs. I just assumed the same issue may transfer to the std::stream case.
It's very possible I'm wrong and ignorant.

/Eric



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [libcxx] Why the type of (w)cin/(w)cout/(w)cout are char []?

Neil Nelson via cfe-dev


From: Eric Fiselier via cfe-dev
Sent: Tuesday, May 17, 2016 10:17
To: Howard Hinnant
Reply To: Eric Fiselier
Cc: Clang Dev
Subject: Re: [cfe-dev] [libcxx] Why the type of (w)cin/(w)cout/(w)cout are char []?

>> Dropping the list. 

> Or not.

‎Nothing to see here.. move along

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev