delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2007/10/24/15:21:53

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" <Robert_Goddard AT apl DOT washington DOT edu>
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
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: <cygwin.cygwin.com>
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
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 <string>
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 <cassert>
# 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/

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019