g ++ странное предупреждение - PullRequest
4 голосов
/ 10 апреля 2011

Работая над игрушечным проектом, на который я начал отвечать на вопрос SO, меня затопляет предупреждение g ++, которого я не понимаю.

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

поиск в интернете У меня сложилось впечатление, что этот может быть ошибкой g ++; действительно ли это ошибка, и если да, то есть ли обходной путь для этого? Полный исходный код слишком велик для включения, но доступно здесь . Вот та часть, где сработало предупреждение ...

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.

EDIT

Очевидно, ошибка связана с использованием итераторов карт, которые могут генерировать встроенный код, который сбивает с толку оптимизатор. Переписав раздел, избегая использования итераторов, я получил более короткий код, который также компилируется без предупреждений.

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

Ответы [ 3 ]

4 голосов
/ 10 апреля 2011

Насколько я могу судить, на самом деле это происходит из кода в 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;
}
0 голосов
/ 10 апреля 2011

-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.

0 голосов
/ 10 апреля 2011

Я видел эту «ошибку» раньше и решил, что она часто бессмысленна. Я не вижу ничего плохого в вашем коде. Вы можете попытать счастья с более новыми версиями GCC - мне кажется, я помню, что это всплыло где-то в районе 4.3-4.4.

Редактировать: я сказал, что это предупреждение / ошибка "часто" не имеет смысла. Как правило, не." Я абсолютно не рекомендую просто игнорировать или отключать предупреждения только потому, что они раздражают, но в этом коде и в некоторых моих собственных кодах нет явных проблем, несмотря на жалобу GCC.

...