g++奇怪的警告
在从事一个玩具项目时,我开始回答一个 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 行左右。
编辑
显然,该错误与使用映射迭代器有关,该迭代器可以生成混淆优化器的内联代码。重写一个部分,避免使用迭代器,我得到了更短的代码,也可以干净地编译而没有警告。
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;
}
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
据我所知,这实际上源于
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中的警告?
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?
-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-别名.html。
-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.
我以前见过这个“错误”,并认为它通常毫无意义。我没有看到你的代码有什么问题。您可以使用较新版本的 GCC 碰碰运气——我似乎记得在 4.3-4.4 左右的某个地方看到过这个弹出窗口。
编辑:我说这个警告/错误“通常”毫无意义。不是“通常”。我绝对不主张仅仅因为警告很烦人就简单地忽略或禁用警告,但是在这段代码以及我自己的一些代码中,尽管 GCC 抱怨,但并没有明显的问题。
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.