g++奇怪的警告
g++ strange warning
我正在做一个玩具项目,当我开始回答一个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提出了抱怨,但没有明显的问题。
- 警告处理为错误这里有什么问题
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- cppcheck在const std::string[]上引发警告
- GCC对可能有效的代码抛出init list生存期警告
- 如何在BST的这个简单递归实现中消除警告
- 关于std::move的使用,是否有编译警告
- g++ 在某个类成员未初始化时不发出警告
- 如何处理来自核心指南检查器的关于gsl::at的静态分析警告
- 使用typeid警告未使用的变量
- 示例C++项目编译中的警告
- 警告:在函数返回类型 [-Wignore 限定符] 时忽略类型限定符
- 如何修复编译器警告 C6386 和 C6385?
- 返回语句后的代码,没有警告
- 获取隐式转换溢出从无符号到已签名的警告
- 编译器警告:执行到达值返回函数的末尾而不返回值
- 在未链接的部分上生成警告
- 警告 C4552:">>":未使用表达式的结果
- 禁止显示由于常量为零而比较始终为假的警告
- C++ 警告:将新创建的 gsl::owner<> 分配给非所有者
- 为什么布尔开关语句有编译器警告?