X-Recipient: archive-cygwin AT delorie DOT com X-Spam-Check-By: sourceware.org Message-ID: <471F9B37.3050305@apl.washington.edu> Date: Wed, 24 Oct 2007 12:21:27 -0700 From: "Robert P. Goddard" User-Agent: Thunderbird 2.0.0.6 (Windows/20070728) MIME-Version: 1.0 To: cygwin AT cygwin DOT com Subject: Re: BUG REPORT: Cygwin, g++, -O2, static member function, std::string Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Antivirus: Scanned by F-Prot Antivirus (http://www.f-prot.com) Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com This is a reply to the message http://cygwin.com/ml/cygwin/2007-10/msg00509.html: The linker is supposed to resolve a function-local static variable into one exactly one instance, constructed on the first call, even if the function is expanded in-line from multiple compilation units. It seems that the problem is not just multiple in-line expansions, but the fact that there is no obvious "home" compilation unit for this header-only class. The following variant on Brad's example shows this: -------------- Cut Here test2.sh --------------- #! /bin/bash # echo "A Cygwin g++ -O2 Bug Report:" echo "RESULT: This slightly modified version works" echo "SIDE EFFECTS: the files ./bug0.hpp, bug1.cpp, and bug2.cpp are created." echo "RUN TEST: ./test2.sh" # cat << EOF > bug0.hpp # include class Element { public: std::string file; ~Element(); static Element *root(void) { static Element r; return &r; } }; EOF cat << EOF > bug0.cpp # include "bug0.hpp" Element::~Element(){} EOF cat << EOF > bug1.cpp # include "bug0.hpp" extern void bug2(void); int main(void) { std::string str("A"); char c = str[0]; Element *r = Element::root(); bug2(); return 0; } EOF cat << EOF > bug2.cpp # include # include "bug0.hpp" void bug2(void) { Element *r = Element::root(); Element *s = Element::root(); assert( r != 0 ); } EOF echo "g++ bug1.cpp bug2.cpp bug0.cpp -O1 -o bug.exe" g++ bug1.cpp bug2.cpp bug0.cpp -O1 -o bug.exe echo "./bug" ./bug echo "g++ bug1.cpp bug2.cpp bug0.cpp -O2 -o bug.exe" g++ bug1.cpp bug2.cpp bug0.cpp -O2 -o bug.exe echo "./bug" ./bug -------------- Cut Here --------------- Here, the offending function is still in-line and still invoked from two places, but I have added a destructor and implemented it in one place. That's enough to make it work. It's still a bug in the linking process, in that it doesn't conform to the C++ standard. Brad's original version should have worked. Header-only libraries are very common, especially where templates are involved, so this is not unimportant. By the way, it's not just a g++ problem. Brad's original code (minus .exe) runs just fine under Linux using an even older version of g++ (3.2.3 on my Linux, vs. 3.4.4 under Cygwin). Bob Goddard -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/