written on Saturday, August 7, 2010
Everybody knows C++ build errors are one of the most bizarre anyone will ever find in the compiled languages world and, by knowing that, it seems that the developers treat new introduced oddities as a normal thing.
Don't get me wrong, I'm not a C++ hater [1] and I didn't come here to rant about the well known and blatantly ugly compilation errors caused by any kind of incorrect Template and/or Overloading usage. What made me come home and write this post was this question on Stackoverflow.com.
Just reading the question and it's answer is enough to get sick. This is basically what goes on:
A fella decides to try out C++0x's standard multithreading support and uses the following code:
#include <iostream>
#include <thread>
void hello() {
std::cout << "Hello Concurrent World";
}
int main(int argc, char *argv[]) {
std::thread t(hello);
t.join();
}
He says he compiled it with g++ -std=c++0x -g -o executable source.cpp and there were no errors, but when running he got a weird Segmentation Fault:
Program received signal SIGSEGV, Segmentation fault.
_dl_fixup (l=0x7ffff7b0992c, reloc_arg=<value optimized out>) at ../elf/dl-runtime.c:147
147 ../elf/dl-runtime.c: No such file or directory.
in ../elf/dl-runtime.c
When trying his code on my box, I got this:
terminate called after throwing an instance of 'std::system_error' what(): Aborted
Which is not as ugly, but still very weird and non informative. Examining the backtrace we get not even a single decent hint about what may be going on:
0xb7fe1424 in __kernel_vsyscall () 0xb7d67d61 in raise () from /lib/libc.so.6 0xb7d695ee in abort () from /lib/libc.so.6 0xb7f7bcd5 in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/libstdc++.so.6 0xb7f79bd5 in ?? () from /usr/lib/libstdc++.so.6 0xb7f79c12 in std::terminate() () from /usr/lib/libstdc++.so.6 0xb7f79d81 in __cxa_throw () from /usr/lib/libstdc++.so.6 0xb7f1eee9 in std::__throw_system_error(int) () from /usr/lib/libstdc++.so.6 0xb7f721d0 in std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>) () from /usr/lib/libstdc++.so.6 0x08048dd2 in thread<void (*)()> (this=0xbffff53c, __f=0x8048b0f <hello()>) at /usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/thread:135
Now, if you're even a little bit used to programming with threads on C or C++ you might just have noted that there's no flag being given to g++ to link the binary against a threading library (pthread, for example, on Linux) and that's exactly the issue here. He should have compiled his code with g++ -std=c++0x -g -pthread -o executable source.cpp.
How fucked up is that? I mean, it's logical that one should need to link against a threading library (even though I believe that this should be automatically resolved by the compiler, being part of the standard and such), but no error at all while compiling? Wtf? That's not an unauthorized access to private memory, null-pointer dereference nor anything like that, it's a linking issue and must cause an error no matter what.
I'm obviously being too harsh with all this. C++0x is not a released standard yet and g++'s implementation is based on the draft, which is constantly (not that much anymore) changing, so perhaps there was not enough time/interest to focus on these "usability" issues. I just hope this behavior changes. Soon.
| [1] | Though, if given the choice and it sounds reasonable, I'd definitely stick to plain C most of the cases. I'd rather glue Python and C together if the only argument for using C++ is being able to "properly" use OOP. |