4

Working on a toy project that I started to answer an SO question I'm getting flooded by a g++ warning that I don't understand.

format.hpp:230: warning: dereferencing pointer ‘<anonymous>’
does break strict-aliasing rules

searching on the internet I've got the impression that this could be a g++ bug; is it really a bug and if yes is there any workaround for it? The full source code is too big for inclusion but is available here. Here is the part where the warning is triggered...

template<typename T>
class ValueWrapper : public ValueWrapperBase
{
public:
    T x;
    ValueWrapper(const T& x) : x(x) {}
    virtual std::string toString(const Field& field) const
    {
        return Formatter<T>().toString(x, field);
    }
private:
    // Taboo
    ValueWrapper(const ValueWrapper&);
    ValueWrapper& operator=(const ValueWrapper&);
};

typedef std::map<std::string, ValueWrapperBase *> Env;

class Dict
{
private:
    Env env;

public:
    Dict() {}
    virtual ~Dict()
    {
        for (Env::iterator i=env.begin(), e=env.end(); i!=e; ++i)
            delete i->second;
    }

    template<typename T>
    Dict& operator()(const std::string& name, const T& value)
    {
        Env::iterator p = env.find(name);
        if (p == env.end())
        {
            env[name] = new ValueWrapper<T>(value);
        }
        else
        {
            ValueWrapperBase *vw = new ValueWrapper<T>(value);
            delete p->second;
            p->second = vw;
        }
        return *this;
    }

    const ValueWrapperBase& operator[](const std::string& name) const
    {
        Env::const_iterator p = env.find(name);
        if (p == env.end())
            throw std::runtime_error("Field not present");
        return *(p->second);
    }

private:
    // Taboo
    Dict(const Dict&);
    Dict& operator=(const Dict&);
};

Line 230 is p->second = vw;.

I get the warning for every instantiation of the template method operator(), always about line 230.

EDIT

Apparently the bug is about the use of map iterators that can generate inline code that confuses the optimizer. Rewriting a section avoiding using iterators I got shorter code that also compiles cleanly without warnings.

template<typename T>
Dict& operator()(const std::string& name, const T& value)
{
    ValueWrapperBase *vw = new ValueWrapper<T>(value);
    ValueWrapperBase *& p(env[name]);
    delete p;
    p = vw;
    return *this;
}
6502
  • 112,025
  • 15
  • 165
  • 265
  • 1
    Are you using optimizations to build? – JackMc Apr 10 '11 at 14:11
  • Can you post the code from near lines 230? – Nawaz Apr 10 '11 at 14:12
  • I normally compile with g++ -O2 -Wall to catch most possible errors (-Wall without -O2 finds a lot less of them because flow analysis is not performed) – 6502 Apr 10 '11 at 14:13
  • Try -Wno-strict-aliasing – Sam Miller Apr 10 '11 at 14:13
  • @Sam Miller: Thanks: that fixes it. But is it really a bug or my code is doing something wrong? – 6502 Apr 10 '11 at 14:20
  • How do you invoke `g++`? `-Wstrict-aliasing=2` sometimes gives false positives, but regular `-Wall` shouldn't. – jalf Apr 10 '11 at 14:40
  • 1
    @6502: just to be clear, do you understand what the warning *normally* means, and are asking why *this* specific code violates the aliasing rules, or don't you understand the warning *at all*? – jalf Apr 10 '11 at 14:44
  • @Jalf: Makefile contains simply `g++ -Wall -O2 -otest_format test_format.cpp`, now I added `-Wno-strict-aliasing` just to stop the complaints. – 6502 Apr 10 '11 at 14:51
  • 1
    @Jalf: Sure I understand the meaning of the warning, but I don't understand why I'm getting it here. I'm doing no tricks with pointers or unions so I don't understand what aliasing g++ is talking about. – 6502 Apr 10 '11 at 14:52

3 Answers3

4

As far as I can tell this actually stems from code in map and not from your code itself.

According to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42032 and http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43978 which both deal with maps and are very similar to each other, that there are absolutely some cases where it warns incorrectly because it loses track of the dynamic types of the objects. They equally state that there are some cases where it warms properly.

Also they indicate that the warning is shushed in 4.5 until they can implement it properly.

Finally, did you try rewriting your method as follows to see if it helps the warning in 4.3/4.4?

template<typename T>
Dict& operator()(const std::string& name, const T& value)
{
    ValueWrapperBase *vw = new ValueWrapper<T>(value);
    delete env[name];
    env[name] = new ValueWrapper<T>(value);

    return *this;
}
Mark B
  • 95,107
  • 10
  • 109
  • 188
  • 1
    @6502, Note that the warning is followed by `/usr/include/c++/4.4/bits/stl_tree.h:179: note: initialized from here` hinting at the origin of the problem. That points to the operator-> which cast pointers. Probably in a safe way, but enough to confuse the warning logic. – AProgrammer Apr 10 '11 at 16:12
  • This seems to me a bug in g++, but following your example and rewriting the code avoiding using the iterator I got it compiling cleanly anyway (and the code is also shorter). See my edit. – 6502 Apr 10 '11 at 16:56
0

I've seen this "error" before and decided that it's often meaningless. I don't see anything wrong with your code. You might try your luck with newer versions of GCC--I seem to recall seeing this pop up somewhere around 4.3-4.4.

Edit: I said this warning/error is "often" meaningless. Not "usually." I absolutely do not advocate simply ignoring or disabling warnings just because they are annoying, but in this code, and in some of my own code, there is no apparent problem despite GCC's complaint.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • +1 to counter unexplained -1: and thanks, so this apparently is really a g++ bug. Now I understand why sometimes I see projects using `-Wno-string-aliasing` in build scripts. – 6502 Apr 10 '11 at 14:40
  • 1
    @6502: no, projects use that because they're badly written, and violate the C++ standard, so they need to disable a very useful (and valid) optimization. The warning is normally *not* a bug, and you should not just assume that it is, unless you *want* your code to invoke undefined behavior. – jalf Apr 10 '11 at 14:47
  • It may or may not be a compiler bug in your specific case, but in the general case, it is not. – jalf Apr 10 '11 at 14:48
  • 3
    @John: no, GCC just started following the standard more strictly around those versions (because it allows for more aggressive optimizations). Unfortunately, a lot of programmers don't understand C++'s aliasing rules, and assume that the warning can be ignored. – jalf Apr 10 '11 at 14:50
  • @Jalf: What is the UB that you think I am triggering in my code? – 6502 Apr 10 '11 at 14:57
  • 1
    @6502: no, I can't see a problem in your code (otherwise I would have left an answer), but @John seems to imply that the warning is *usually* meaningless, which is certainly not the case. I wouldn't accept this as an answer unless he at least clarifies that he's not talking about strict-aliasing warnings *in general*. – jalf Apr 10 '11 at 14:58
  • I said this warning/error is "often" meaningless. Not "usually." I absolutely do not advocate simply ignoring or disabling warnings just because they are annoying, but in this code, and in some of my own code, there is no apparent problem despite GCC's complaint. – John Zwinck Apr 10 '11 at 15:03
  • @John: then it would be nice to clarify this in your answer. Some clueless newbie might see this answer next week, and interpret it as "this compiler warning just means GCC is buggy" if you don't specify the circumstances under which the warning can be ignored. – jalf Apr 10 '11 at 15:08
  • While I think that your answer is correct and I really do not understand the downvotes, I actually ended up rewriting offending code without iterators and this made the warning disappear (so I'm back to `-Wall -O2` that I like to use). Still to me looks a bug in g++ and may be there are more complex cases in which the only solution is just to shut up the broken compiler on this issue. My is just wild guessing (I never looked at g++ code or even at their standard library implementation) but looks like the problem here is with inlining map iterators that confuses the optimizer. – 6502 Apr 10 '11 at 18:31
  • Yeah the downvoters haven't explained themselves. Probably knee-jerk reactions by people not plagued by this particular warning. I know I'd usually have a negative reaction to someone saying "Just tell the compiler to shut up," but this case is rather special. Oh well, I'm leaving the answer here because at least a few of us believe it's valid. For what it's worth, in my own code I let the compiler emit the warnings, and hope that one day GCC will fix the bug (whether in the compiler itself or in its STL implementation). – John Zwinck Apr 10 '11 at 19:09
0

-fno-strict-aliasing (see http://gcc.gnu.org/onlinedocs/gcc-4.2.4/gcc/Optimize-Options.html#index-fstrict_002daliasing-572) turns off gcc's strict aliasing optimisations, and (presumably) with it the warning.

See also What is the strict aliasing rule? and http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html.

Community
  • 1
  • 1
  • I'm using no unions and no pointer casting tricks (actually IIRC there's no pointer casting at all in the whole project). – 6502 Apr 10 '11 at 14:45
  • gcc is probably wrong to emit the error, then. To my way of thinking, turning off strict aliasing is better than suppressing a warning that you're unable to fix. –  Apr 10 '11 at 21:11