g++奇怪的警告

g++ strange warning

本文关键字:警告 g++      更新时间:2023-10-16

我正在做一个玩具项目,当我开始回答一个SO问题时,我被一个我不理解的g++警告淹没了。

format.hpp:230: warning: dereferencing pointer ‘<anonymous>’
does break strict-aliasing rules
在网上搜索

,我得到的印象是这个可能是一个g++的错误;这真的是一个bug吗?如果是,有什么解决办法吗?完整的源代码太大,无法包含,但可以在这里获得。下面是触发警告的部分…

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&);
};

第230行是p->second = vw;

每次实例化模板方法operator()时,我都会得到警告,总是在第230行左右。

编辑

显然这个bug是关于map迭代器的使用,它可以生成内联代码,从而混淆优化器。重写一个section,避免使用迭代器,我得到了更短的代码,并且编译干净,没有警告。

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;
}

据我所知,这实际上源于map中的代码,而不是您的代码本身。

根据http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42032和http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43978,两者都处理地图,彼此非常相似,绝对有一些情况下,它警告不正确,因为它失去了对象的动态类型的跟踪。他们同样指出,在某些情况下,温度会适当升高。

他们还指出,警告在4.5中被隐藏,直到他们可以正确地实现它。

最后,您是否尝试重写您的方法如下,看看它是否有助于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;
}

-fno-strict-aliasing(参见http://gcc.gnu.org/onlinedocs/gcc-4.2.4/gcc/Optimize-Options.html#index-fstrict_002daliasing-572)关闭了gcc的严格别名优化,并且(可能)会发出警告。

参见什么是严格的混叠规则?和http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html。

我以前见过这种"错误",并认为它通常是没有意义的。我看不出你的代码有什么问题。你可以试试新版本的GCC——我似乎记得在4.3-4.4的某个地方看到过这个弹出框。

编辑:我说过这个警告/错误"经常"没有意义。而不是"通常"。我绝对不提倡仅仅因为警告令人讨厌而忽略或禁用它们,但是在这段代码中,以及在我自己的一些代码中,尽管GCC提出了抱怨,但没有明显的问题。