在我开始回答一个问题的玩具项目上,我被一个我不理解的g ++警告所淹没。
format.hpp:230: warning: dereferencing pointer ‘<anonymous>’
does break strict-aliasing rules
在互联网上搜索我的印象是可能是一个g ++错误;它真的是一个错误,如果是的话有任何解决方法吗?完整的源代码太大而无法包含is available here。这是触发警告的部分......
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迭代器。重写一个避免使用迭代器的部分我得到了更短的代码,它也可以在没有警告的情况下干净地编译。
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;
}
答案 0 :(得分:4)
据我所知,这实际上源于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;
}
答案 1 :(得分:0)
我之前看过这个“错误”,并认为它通常毫无意义。我没看到你的代码有什么问题。你可以尝试使用更新版本的GCC - 我似乎记得在4.3-4.4左右看到这个弹出窗口。
编辑:我说这个警告/错误“经常”毫无意义。不是“通常”。我绝对不提倡仅仅因为它们很烦人而忽略或禁用警告,但在这段代码中,以及在我自己的一些代码中,尽管有GCC的投诉,但没有明显的问题。
答案 2 :(得分:0)
-fno-strict-aliasing
(请参阅http://gcc.gnu.org/onlinedocs/gcc-4.2.4/gcc/Optimize-Options.html#index-fstrict_002daliasing-572)关闭了gcc严格的别名优化,并且(大概)会发出警告。
另请参阅What is the strict aliasing rule?和http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html。