g ++:-O1 -fdevirtualize -flto导致ifstream :: widen出现问题

时间:2015-09-02 03:42:53

标签: optimization g++ vtable

如果我将以下代码放在test.cpp

#include <fstream>
int main(int argc, char ** argv) {
    std::ifstream a;
    do{
        a.widen('\n');
    }while(true);
}

并使用

调用g ++
g++ -O1 -fdevirtualize -flto -m64 -o out Tergiversative.cpp

在g ++版本5.1.0上,生成的可执行文件在第一次调用a.widen时崩溃。如果我把它包裹在(例如)

中,这不会发生
do{
    a.widen('\n');
}while(false);

因为它只是&#34;扁平化&#34;,但它确实发生在任何其他循环中,如

int i=2;
do{
    a.widen('\n');
    i--;
}while(i>0);

具体而言,在ctype<char> widen内,它到达(来自locale_facets.h

widen(char __c) const{
  if (_M_widen_ok)
    return _M_widen[static_cast<unsigned char>(__c)];
  this->_M_widen_init();
  return this->do_widen(__c);
}

它对do_widen进行虚拟调用。当上述三个标志中的任何一个被禁用时,这样可以正常工作;当所有三个都启用时,vtable不会以某种方式正确填充,并且do_widen指针保持为NULL,在运行时给出SIGSEGV。当它没有被置于一个循环中(或者是一个简单的循环,比如do / while(false)),那么g ++会将上述内容转换为对std::basic_ios<char,std::char_traits<char>>::widen('\n')的调用,并且没有任何不好的事情发生。

我的代码调用未定义的行为有什么问题吗?或者这是一个奇怪的边缘情况,在我触发的某些优化中?我只是在构建64位可执行文件(-m32使其运行正常)时才会发生这种情况,而且只有-O1 -fdevirtualize -flto。我检查了由-O1转换的每个子标志,但它们没有触发它,所以它必须是&#34;隐形&#34;之一。优化直接检查-On级别。 -fdevirtualize相关的{{1}}是有意义的,因为它是一个失败的虚拟电话 - 但是 电话没有被虚拟化了。 vtable只是无人居住。

任何帮助理解这一点都将不胜感激!

0 个答案:

没有答案