Unused const object of class with virtual desctructor causes segmentation fault - c++

I was struggling with segmentation fault after returning from main in C++0x code compiled under GCC with MinGW, and have narrowed it to simple case:
class A {
public:
virtual ~A();
};
A::~A() {
}
const A a;
int main() {
return 0;
}
The reason is correlated with:
const qualifier before object, removing it stops seg fault,
Lack of constructor in class A - adding empty one stops seg fault.
Version of compialtor - newer TDM MinGW with gcc 4.8.1 does not build code causing seg fault.
Am I triggering some undefined behavior, or really compiler bug is reason of such behavior?
Affected compiler:
gcc --version
gcc.exe (tdm-1) 4.7.1
g++ --version
g++.exe (tdm-1) 4.7.1
ld --version
GNU ld (GNU Binutils) 2.22

This appears to be gcc bug 55893 that was fixed in 4.7.3. The attached testcase is very similar to yours:
struct foo
{
virtual ~foo () { }
};
int main ()
{
static const foo tmp;
}
The error occurs because gcc places the const object in read-only memory, because it is trivially constructible, without checking that the object has a non-trivial destructor. The destructor, being virtual, attempts to update the vtable pointer, leading to the segfault.

Related

thread_local template variable of struct inside anonymous namespace fails to link?

The following example program uses a thread local template variable, and instantiates it using a type inside an anonymous namespace. This produces a linker error in gcc. In clang it actually compiles but does not run correctly.
#include <stdio.h>
template<typename T>
struct container {
container() { printf("construct: %p\n", this); }
~container() { printf("destruct: %p\n", this); }
};
template<typename T>
thread_local container<T> storage;
namespace {
struct bar {};
}
int main() {
auto& ref1 = storage<bar>;
auto& ref2 = storage<bar>;
}
On gcc this fails with a link error:
a.cpp:6:2: warning: ‘container<T>::~container() noexcept [with T = {anonymous}::bar]’ used but never defined
~container() { printf("destruct: %p\n", this); }
^
/tmp/ccgh0P15.o: In function `__tls_init':
a.cpp:(.text+0xa9): undefined reference to `container<(anonymous namespace)::bar>::~container()'
With clang the program compiles but produces very troubling output:
construct: 0x7fb8d1c003d0
construct: 0x7fb8d1c003d0
destruct: 0x7fb8d1c003d0
destruct: 0x7fb8d1c003d0
Are there some rough edges surrounding thread_local/templated variables that I am running into here? I am unclear why this would ever produce a link error (the link error disappears if I remove thread_local). In the case of clang how could a double destroy of an object with static storage duration be anything but a compiler bug? In clang the issue disappears if I remove the anonymous namespace OR the thread_local specification, OR by removing one of the references in main().
Can anyone shed some light on this, I am mainly just curious if I am misunderstanding something. Thanks!
EDIT:
clang++ -v
Apple LLVM version 10.0.0 (clang-1000.11.45.5)
g++ -v
gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)

"pure virtual function called" on gcc 4.4 but not on newer version or clang 3.4

I've got an MCVE which, on some of my machines crashes when compiled with g++ version 4.4.7 but does work with clang++ version 3.4.2 and g++ version 6.3.
I'd like some help to know if it comes from undefined behavior or from an actual bug of this ancient version of gcc.
Code
#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!
}
}
Compile & run
g++ -O1 -Wall -Werror thebug.cpp && ./a.out
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
This is actually minimal, if one removes any feature of this code, it runs correctly.
Analyse
The code snippet works fine when compiled with -O0, BUT it still works fine when compiled with -O0 +flag for every flag of -O1 as defined on GnuCC documentation.
A core dump is generated from which one can extract the backtrace:
(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 ()
Feel free to ask for tests or details in the comments.
Asked:
Is it the actual code? Yes! it is! byte for byte. I've checked and rechecked.
What exact version of GnuCC du you use?
$ 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.
Can we see the generated assembly? Yes, here it is on pastebin.com
This is a Red Hat-specific bug not present in FSF GCC. It is not a problem in your code.
On a system with both CentOS 6's GCC, and FSF GCC 4.4.7, having both generate an assembly listing and viewing the differences between the two, one bit jumps out:
CentOS 6's GCC generates
movq $_ZTV8BaseType+16, (%rsp)
whereas FSF GCC 4.4.7 generates
movq $_ZTV11TypeTextFix+16, (%rsp)
In other words, one of Red Hat's GCC patches makes it set up the vtable incorrectly. This is part of your main function, you can see it in your own assembly listing shortly after .L48:.
Red Hat applies many patches to its version of GCC, and some of them are patches that affect code generation. Unfortunately, one of them appears to have an unintended side effect.
Though the true solution to this bug would be not to use RedHat GnuCC 4.4.7 (or any RedHat compiler...), we are temporarily stuck with this version.
We did find an alternative: obfuscate the constructor of BaseType to the compiler hence preventing it to over-optimize it. We did it simply by defining BaseType::BaseType() in a separate translation unit.
Doing so bypass g++ bug. We did indeed checked that both BaseType and TypeTextFix virtual table pointers were written to constructed object before calling its related constructors.

Clang warning in dubious case: function 'foo' could be declared with attribute 'noreturn'?

I have been playing around a bit with the [[noreturn]] attribute, which I'm trying to get a handle of and make use of (I understand [[noreturn]] is a C++11 standard attribute and __attribute__((noreturn)) is a GCC/Clang extension). As part of this, I enabled the Clang warning -Wmissing-noreturn.
> clang++ -v
Ubuntu clang version 3.7.1-svn253742-1~exp1 (branches/release_37) (based on LLVM 3.7.1)
Target: x86_64-pc-linux-gnu
Thread model: posix
foo.cpp:
enum bar
{
A = 1,
B,
C
};
void foo()
{
switch (bar())
{
case A:
case B:
case C:
default:
break;
}
}
int main()
{
foo();
return 0;
}
Then compile:
> clang++ foo.cpp -o foo -Wmissing-noreturn -std=c++14
foo.cpp:9:1: warning: function 'foo' could be declared with attribute 'noreturn'
[-Wmissing-noreturn]
{
^
1 warning generated.
It appears to me that it would return! What's going on here? Is this a compiler bug?
If you remove the "= 1" from A, then it compiles fine without a warning.
If I do make the foo() function [[noreturn]] void foo(), then it does crash with a segmentation fault.
Ok sorry for delete the last answer. It was wrong. Ok noreturn meann that the function never end. and the segementation fould is because bar is not a variable
Just to give a follow up to an old question: clang is correct, even if a little pedantic.
Indeed the attribute noreturn is applicable to your foo() function, since it doesn't return anything. The fact that clang of 2016 gets confused with the slight variation in the enumeration that is a problem.
But we should forgive clang for this pecadillo, for C++11 grammar is not what could be called very simple.

Why is no 'unused variable' warning given for boost::scoped_lock instances? [duplicate]

boost::mutex::scoped_lock is a handy RAII wrapper around locking a mutex. I use a similar technique for something else: a RAII wrapper around asking a data interface to detach from/re-attach to a serial device.
What I can't figure out, though, is why in the code below only my object mst — whose instantiation and destruction do have side effects — causes g++ to emit an "unused variable" warning error whereas l manages to remain silent.
Do you know? Can you tell me?
[generic#sentinel ~]$ cat test.cpp
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>
struct MyScopedThing;
struct MyWorkerObject {
void a() { std::cout << "a"; }
void b() { std::cout << "b"; }
boost::shared_ptr<MyScopedThing> getScopedThing();
};
struct MyScopedThing {
MyScopedThing(MyWorkerObject& w) : w(w) {
w.a();
}
~MyScopedThing() {
w.b();
}
MyWorkerObject& w;
};
boost::shared_ptr<MyScopedThing> MyWorkerObject::getScopedThing() {
return boost::shared_ptr<MyScopedThing>(new MyScopedThing(*this));
}
int main() {
boost::mutex m;
boost::mutex::scoped_lock l(m);
MyWorkerObject w;
const boost::shared_ptr<MyScopedThing>& mst = w.getScopedThing();
}
[generic#sentinel ~]$ g++ test.cpp -o test -lboost_thread -Wall
test.cpp: In function ‘int main()’:
test.cpp:33: warning: unused variable ‘mst’
[generic#sentinel ~]$ ./test
ab[generic#sentinel ~]$ g++ -v 2>&1 | grep version
gcc version 4.4.5 20110214 (Red Hat 4.4.5-6) (GCC)
Note that the question has changed since the other answers were written.
Likely the reason g++ doesn't warn in the current form is because mst is a reference, and constructing and destructing a reference has no side effects. It's true that here the reference is extending the lifetime of a temporary, which has effects in its constructor and destructor, but apparently g++ doesn't realise that makes a difference.
If my memory serves me right, g++ has the unfortunate habit of emitting unused variable errors differently depending on the optimization settings because the detection works at the optimizer level.
That is, the code is optimized in SSA form, and if the optimizer detects that a variable, after optimization, is unused, then it may emit a warning (I much prefer Clang analysis for this...).
Therefore it is probably a matter of detecting what the destructor does. I wonder if it takes a conservative approach whenever the definition of the destructor is offline, I would surmise this equates a function call then and that the this qualify as a use of the variable.
I suspect the reason is that your class has a trivial
destructor, and that g++ only warns about unused variables if
the destructor is trivial. Invoking a non-trivial destructor is a
"use".

C++ constructor/copy constructor issues in g++ 3.4.6

Here is a code snippet:
class test {
public:
test(){
cout<<"I am in default constructor ";
}
static void func(const test &obj){
cout<<"I am in function ";
}
protected:
test( const test &o){
cout<<"I am in copy constructor ";
}
};
int main()
{
test::func(test());
}
The above code gives following error with g++ 3.4.6 (on Red Hat Linux) on compilation:
In function `int main()':
error: `test::test(const test&)' is protected
error: within this context
However if you compile with g++ 3.3.2 or g++ 4.4.3 or any other g++ version (on Red Hat Linux), it compiles successfully and gives following output:
I am in default constructor I am in function
In the above code, I have passed the temporary object (created by default constructor) to function func by reference. So why the compiler 3.4.6 is calling the copy constructor?
Most likely because older g++ versions (and I believe it stands for other compilers) were not fully c++ compliant and had more bugs then the current version. As you said, this works on a later version, therefore it is most likely fixed.
EDIT
by the way, have you tried changing compiler settings? Different optimization levels might have different bugs.