我有一个MCVE,在我的一些机器上崩溃时使用g ++版本4.4.7编译但是与clang ++版本3.4.2和g ++版本6.3一起使用.
我想要一些帮助来知道它是来自未定义的行为还是来自这个古老版本的gcc的实际错误.
#includeclass BaseType { public: BaseType() : _present( false ) {} virtual ~BaseType() {} virtual void clear() {} virtual void setString(const char* value, const char* fieldName) { _present = (*value != '\0'); } protected: virtual void setStrNoCheck(const char* value) = 0; protected: bool _present; }; // ---------------------------------------------------------------------------------- class TypeTextFix : public BaseType { public: virtual void clear() {} virtual void setString(const char* value, const char* fieldName) { clear(); BaseType::setString(value, fieldName); if( _present == false ) { return; // commenting this return fix the crash. Yes it does! } setStrNoCheck(value); } protected: virtual void setStrNoCheck(const char* value) {} }; // ---------------------------------------------------------------------------------- struct Wrapper { TypeTextFix _text; }; int main() { { Wrapper wrapped; wrapped._text.setString("123456789012", NULL); } // if I add a write to stdout here, it does not crash oO { Wrapper wrapped; wrapped._text.setString("123456789012", NULL); // without this line (or any one), the program runs just fine! } }
g++ -O1 -Wall -Werror thebug.cpp && ./a.out pure virtual method called terminate called without an active exception Aborted (core dumped)
这实际上是最小的,如果删除此代码的任何功能,它将正确运行.
编译时代码片段工作正常-O0
,但是当使用GnuCC文档中定义的-O0 +flag
每个标志进行编译时,它仍然可以正常工作.-O1
生成核心转储,从中可以提取回溯:
(gdb) bt #0 0x0000003f93e32625 in raise () from /lib64/libc.so.6 #1 0x0000003f93e33e05 in abort () from /lib64/libc.so.6 #2 0x0000003f98ebea7d in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib64/libstdc++.so.6 #3 0x0000003f98ebcbd6 in ?? () from /usr/lib64/libstdc++.so.6 #4 0x0000003f98ebcc03 in std::terminate() () from /usr/lib64/libstdc++.so.6 #5 0x0000003f98ebd55f in __cxa_pure_virtual () from /usr/lib64/libstdc++.so.6 #6 0x00000000004007b6 in main ()
请随意在评论中询问测试或详细信息.问:
这是实际的代码吗?是! 它是!字节的字节.我已经检查并重新检查了.
您使用的GnuCC du的确切版本是什么?
$ g++ --version g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16) Copyright (C) 2010 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
我们能看到生成的组件吗?是的,这是在pastebin.com上
小智.. 11
这是FSF GCC中没有的特定于Red Hat的错误.这不是您的代码中的问题.
在同时具有CentOS 6的GCC和FSF GCC 4.4.7的系统上,同时生成汇编列表并查看两者之间的差异,一位跳出:
CentOS 6的GCC产生
movq $_ZTV8BaseType+16, (%rsp)
而FSF GCC 4.4.7则生成
movq $_ZTV11TypeTextFix+16, (%rsp)
换句话说,Red Hat的GCC补丁之一使得它无法正确设置vtable.这是您的main
功能的一部分,您可以在不久之后在您自己的装配清单中看到它.L48:
.
Red Hat在其GCC版本中应用了许多补丁,其中一些是影响代码生成的补丁.不幸的是,其中一个似乎有意想不到的副作用.
这是FSF GCC中没有的特定于Red Hat的错误.这不是您的代码中的问题.
在同时具有CentOS 6的GCC和FSF GCC 4.4.7的系统上,同时生成汇编列表并查看两者之间的差异,一位跳出:
CentOS 6的GCC产生
movq $_ZTV8BaseType+16, (%rsp)
而FSF GCC 4.4.7则生成
movq $_ZTV11TypeTextFix+16, (%rsp)
换句话说,Red Hat的GCC补丁之一使得它无法正确设置vtable.这是您的main
功能的一部分,您可以在不久之后在您自己的装配清单中看到它.L48:
.
Red Hat在其GCC版本中应用了许多补丁,其中一些是影响代码生成的补丁.不幸的是,其中一个似乎有意想不到的副作用.