У меня есть MCVE, который на некоторых моих машинах вылетает при компиляции с g++ версии 4.4.7, но работает с clang++ версии 3.4.2 и g++ версии 6.3.
Мне нужна помощь, чтобы узнать, исходит ли это из поведения undefined или от фактической ошибки этой древней версии gcc.
Код
#include <cstdlib>
class 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
, но он все еще отлично работает при компиляции с -O0 +flag
для каждого флага -O1
, как определено на Документация GnuCC.
Создается дамп ядра, из которого можно извлечь обратную трассировку:
(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 вы используете?
$ 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