LTO causes crash in standard library - c++

Consider the following program:
#include <iostream>
#include <string>
int main()
{
std::string s;
std::getline(std::cin, s);
return 0;
}
I try to build it with various flags and run as echo foo | ./prog.
If I build it with clang 5.0 or gcc 7.1 (or 7.2) with optimization from -O0 to -O3, it works as expected. But if I add -flto to any of these configurations, it crashes immediately with the following backtrace:
/lib64/libc.so.6(+0x721af)[0x7f596b08e1af]
/lib64/libc.so.6(+0x77706)[0x7f596b093706]
/lib64/libc.so.6(+0x78453)[0x7f596b094453]
/usr/lib64/libstdc++.so.6(_ZNSs7reserveEm+0x85)[0x7f596b9ac055]
/usr/lib64/libstdc++.so.6(_ZSt7getlineIcSt11char_traitsIcESaIcEERSt13basic_istreamIT_T0_ES7_RSbIS4_S5_T1_ES4_+0x175)[0x7f596b984c05]
./a.out[0x400d7d]
./a.out[0x400c32]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f596b03c6e5]
./a.out[0x400ab9]
Valgrind reports the same in a slightly more readable way:
==30863== Invalid free() / delete / delete[] / realloc()
==30863== at 0x4C2A8DC: operator delete(void*) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==30863== by 0x4F0E054: std::string::reserve(unsigned long) (in /usr/lib64/libstdc++.so.6.0.24)
==30863== by 0x4EE6C04: std::basic_istream<char, std::char_traits<char> >& std::getline<char, std::char_traits<char>, std::allocator<char> >(std::basic_istream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char) (in /usr/lib64/libstdc++.so.6.0.24)
==30863== by 0x40091B: main (in /path/to/prog)
==30863== Address 0x6011c0 is 0 bytes inside data symbol "_ZNSs4_Rep20_S_empty_rep_storageE"
Also it works OK with --std=c++14 and below even with LTO enabled.
So what is the problem? Is it a bug in LTO implementation for C++17 in both compilers? Or just the libstdc++ is compiled with wrong flags? I use opensuse 42.3 and the standard library is installed from repositories.
Can it be worked around somehow?

For gcc this looks like this bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82172.
There are a number of workarounds, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82172#c3. One of them is to use -D_GLIBCXX_USE_CXX11_ABI=1:
g++ -D_GLIBCXX_USE_CXX11_ABI=1 --std=c++17 -flto prog.cpp
See also the same problem here flto crash with gcc7.2.

Following ks1322's links, I finally landed to binutils bug page, which
describes the root of the problem.
The bug was finally fixed in binutils 2.30 and backported to binutils 2.29 and 2.28. Updating to binutils 2.29 fixed the test example, but my actual build was still affected.
I figured out that one of my project's dependencies (I use CMake and external project module) was build without LTO. Adding -flto to all dependencies and using appropriate archiver (i.e. gcc-ar instead of ar) solved the problem completely.

Related

Boost:;program_options 1.49 - can't link with -lboost_program_options

I'm attempting my first use of Boost anything so I thought I'd start with program_options. I'm developing on a Raspberry Pi running Debian Wheezy. I started by "apt-get install libboost1.49-all" and everything seemed to install correctly. I can see .a and .so libraries in /usr/lib.
/usr/lib/libboost_program_options.a
/usr/lib/libboost_program_options-mt.a -> libboost_program_options.a
/usr/lib/libboost_program_options-mt.so -> libboost_program_options.so.1.49.0
/usr/lib/libboost_program_options.so -> libboost_program_options.so.1.49.0
/usr/lib/libboost_program_options.so.1.49.0
I can compile some example source I found here by using
g++ boost_program_options.cpp -c
but I cannot get anything to link. I've tried explicitly specifying the library path using no -l and got nothing but several pages of undefined reference errors. I tried another example code and got a compile problem that indicated to me that I wasn't using "g++ -std=c++0x" but that's not the problem either. I'm stuck. I've also tried
g++ -std=c++0x boostme.cpp -o boostme -L/usr/lib -lboost_program_options
I'm just banging my head against the wall at this point. Among the stackoverflow posts I've seen so far, I'm doing everything correctly. My head hurts. ;-)
Just some sample error messages below. Still poking around.
/tmp/ccTbmurt.o: In function `boost::program_options::error_with_option_name::~error_with_option_name()':
boostme.cpp:(.text._ZN5boost15program_options22error_with_option_nameD2Ev[_ZN5boost15program_options22error_with_option_nameD5Ev]+0x118): undefined reference to `vtable for boost::program_options::error_with_option_name'
/tmp/ccTbmurt.o: In function `boost::program_options::validation_error::validation_error(boost::program_options::validation_error::kind_t, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)':
boostme.cpp:(.text._ZN5boost15program_options16validation_errorC2ENS1_6kind_tERKSsS4_i[_ZN5boost15program_options16validation_errorC5ENS1_6kind_tERKSsS4_i]+0x30): undefined reference to `boost::program_options::validation_error::get_template(boost::program_options::validation_error::kind_t)'
Because the signature of that destructor really should be
~error_with_option_name() throw() {}
I'm going to look into my crystal ball and say that - maybe - somewhere you might have #define throw() or similar hidden in your codebase.
That, or you might have conflicting version of the header files in your include paths, which do not correspond to the version of the libraries found at link time

Errors with regex on Ubuntu

I've a problem with using regex on Ubuntu,on Qt platform(I tried on Code::Blocks,too). I'm writing console application code and I must use regex.
When I typed #include <regex>,It to me that error(I think it's the most important error,but there are many errors of regex):
/usr/include/c++/4.9/bits/c++0x_warning.h:32: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
#error This file requires compiler and library support for the \
^
And I thought that I should use Boost library. I installed Boost with:
sudo apt-get install libboost-all-dev
and typed(and I edited things,with writing boost:: in the beginning):
#include <boost/regex.hpp>
But,unfortunately,It caused many errors,Like that:
In function `bool boost::regex_search<__gnu_cxx::__normal_iterator<char const*, std::string>, char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >(__gnu_cxx::__normal_iterator<char const*, std::string>, __gnu_cxx::__normal_iterator<char const*, std::string>, boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags)':
I'm really puzzled what I should to do.
You did not include the error message produced by <boost/regex.hpp>. Regarding the regex header provided by the standard library, the error message says it all: You have to use at least C++11, to have access to that header. E.g:
g++ -std=c++11 -Wall -Wextra -Werror foobar.cpp

How to link in std C++ library on Mac OS X Mavericks?

I'm porting an application to OS X Darwin and am getting link errors with missing symbols like:
std::__1::basic_string<char, std::__1::char_traits<char>,
std::__1::allocator<char> >::find_last_of(char const*,
unsigned long,
unsigned long) const
operator delete[](void*)
typeinfo for std::runtime_error
std::set_unexpected(void (*)())
std::exception::~exception()
[...]
I expect these should come from libstdc++ but I don't see how to link that in using clang.
Here is my attempted link line and the resulting failure:
clang -std=c++11 -stdlib=libc++ -m64 -o ARCH.darwin_1310_i86/release/myExec ARCH.darwin_1310_i86/release/myExec.o ../../src/netcomm/ARCH.darwin_1310_i86/release/libmyExec.a ../../src/common/ARCH.darwin_1310_i86/release/libcommon.a -L../zlib -lz -L../Botan -lbotan-1.10 -lboost_thread-mt
Undefined symbols for architecture x86_64:
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::find_last_of(char const*, unsigned long, unsigned long) const", referenced from:
[...]
But this did not work, I'm not finding any examples of how to link it in correctly.
You need to add -lc++ to the link line like this:
clang -std=c++11 -stdlib=libc++ -lc++ -m64 -o ARCH.darwin_1310_i86/release/myExec ARCH.darwin_1310_i86/release/myExec.o ../../src/netcomm/ARCH.darwin_1310_i86/release/libmyExec.a ../../src/common/ARCH.darwin_1310_i86/release/libcommon.a -L../zlib -lz -L../Botan -lbotan-1.10 -lboost_thread-mt
After adding that, the missing symbols go away.
Using the CLang++ compiler on my MacBook Pro OS X Mavericks 9.2, within NetBeans 7.4, I have
-std=c++11 -stdlib=libc++ -Wall
I am sure that I obtained the libc++ from installing the latest Xcode Command Line Tools for Mavericks. On my system, the dynamic libc++ libraries are located in the /usr/lib directory.
Start Edit
I have just tried a basic, "Hello, World," run from Xcode, making sure the LLVM 5.0 (CLang++) compiler settings within the .xcodeproj are configured for:
C++ Language Dialect C++11 [-std=c++11]
C++ Standard Library libc++ (LLVM C++ Standard library with C++11 support)
C Language Dialect c11
All works as expected.
End Edit

Using -std=c++0x with gfortran

I have large program which uses C, C++, and Fortran. I've always found it easiest to get this to link properly using the "gfortran" front end, even though my main is C. gfortran knows about a lot of Fortran special stuff that needs to be linked in.
Now, however, I need to include unordered_map, which with my compiler (gcc 4.4.1 on Mac OS X 10.7.5) seems to require the -std=c++0x option. I discovered and verified that by compiling a small test program with C++ only.
But if I use the -std=c++0x option with gfortran, that produces a huge number of link errors starting with:
Undefined symbols for architecture i386:
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >::data() const", referenced from:
Meanwhile, if I go back to my large program, and replace the gfortran with g++ or gcc, I also get a huge number of link errors, starting with:
Undefined symbols for architecture i386:
"__gfortran_compare_string", referenced from:
I now link using g++ with the -lgfortran switch, and that lets me use -std=c++0x and doesn't leave me with undefined c++ or fortran symbols.

Problem using GMP with Eclipse C++ (CDT Helios)

I would like to compile my code in CDT:
#include <iostream>
#include <gmpxx.h>
using namespace std;
int main (void) {
mpz_class a, b, c;
a = 1234;
b = "-5678";
c = a+b;
cout << "sum is " << c << "\n";
cout << "absolute value is " << abs(c) << "\n";
cin >> a;
return 0;
}
When I compiled, there were some errors like this:
**** Build of configuration Debug for project test ****
**** Internal Builder is used for build ****
g++ -LC:\Dev-Cpp\lib -lgmp -lgmpxx -otest.exe src\test.o
src\test.o(.text$_ZN10__gmp_exprIA1_12__mpz_structS1_ED1Ev[__gmp_expr<__mpz_struct [1], __mpz_struct [1]>::~__gmp_expr()]+0xd): In function `_gmpz_abs':
C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/gmpxx.h: undefined reference to `__gmpz_clear'
src\test.o(.text$_ZN10__gmp_exprIA1_12__mpz_structS1_EaSEPKc[__gmp_expr<__mpz_struct [1], __mpz_struct [1]>::operator=(char const*)]+0x55):C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/gmpxx.h: undefined reference to `__gmpz_set_str'
src\test.o(.text$_ZN10__gmp_exprIA1_12__mpz_structS1_EaSEi[__gmp_expr<__mpz_struct [1], __mpz_struct [1]>::operator=(int)]+0x14):C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/gmpxx.h: undefined reference to `__gmpz_set_si'
src\test.o(.text$_ZN10__gmp_exprIA1_12__mpz_structS1_EC1Ev[__gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr()]+0xd):C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/gmpxx.h: undefined reference to `__gmpz_init'
src\test.o(.text$_ZlsIA1_12__mpz_structERSoS2_RK10__gmp_exprIT_S4_E[std::basic_ostream<char, std::char_traits<char> >& operator<< <__mpz_struct [1]>(std::basic_ostream<char, std::char_traits<char> >&, __gmp_expr<__mpz_struct [1], __mpz_struct [1]> const&)]+0x1c):C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/gmpxx.h: undefined reference to `operator<<(std::ostream&, __mpz_struct const*)'
src\test.o(.text$_ZlsIA1_12__mpz_struct16__gmp_unary_exprI10__gmp_exprIS1_S1_E18__gmp_abs_functionEERSoS7_RKS3_IT_T0_E[std::basic_ostream<char, std::char_traits<char> >& operator<< <__mpz_struct [1], __gmp_unary_expr<__gmp_expr<__mpz_struct [1], __mpz_struct [1]>, __gmp_abs_function> >(std::basic_ostream<char, std::char_traits<char> >&, __gmp_expr<__mpz_struct [1], __gmp_unary_expr<__gmp_expr<__mpz_struct [1], __mpz_struct [1]>, __gmp_abs_function> > const&)]+0x6b):C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/gmpxx.h: undefined reference to `operator<<(std::ostream&, __mpz_struct const*)'
src\test.o(.text$_ZrsIA1_12__mpz_structERSiS2_R10__gmp_exprIT_S4_E[std::basic_istream<char, std::char_traits<char> >& operator>><__mpz_struct [1]>(std::basic_istream<char, std::char_traits<char> >&, __gmp_expr<__mpz_struct [1], __mpz_struct [1]>&)]+0x1c):C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/gmpxx.h: undefined reference to `operator>>(std::istream&, __mpz_struct*)'
src\test.o(.text$_ZN10__gmp_exprIA1_12__mpz_structS1_EC1IS1_16__gmp_unary_exprIS2_18__gmp_abs_functionEEERKS_IT_T0_E[__gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr<__mpz_struct [1], __gmp_unary_expr<__gmp_expr<__mpz_struct [1], __mpz_struct [1]>, __gmp_abs_function> >(__gmp_expr<__mpz_struct [1], __gmp_unary_expr<__gmp_expr<__mpz_struct [1], __mpz_struct [1]>, __gmp_abs_function> > const&)]+0xd):C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/gmpxx.h: undefined reference to `__gmpz_init'
src\test.o(.text$_ZN17__gmp_binary_plus4evalEP12__mpz_structPKS0_S3_[__gmp_binary_plus::eval(__mpz_struct*, __mpz_struct const*, __mpz_struct const*)]+0x1b):C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/gmpxx.h: undefined reference to `__gmpz_add'
src\test.o(.text$__gmpz_abs[___gmpz_abs]+0x1d):C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/../../../../include/gmpxx.h: undefined reference to `__gmpz_set'
collect2: ld returned 1 exit status
Build error occurred, build is stopped
Time consumed: 1514 ms.
What must I do? I've added libgmp.a and libgmpxx.a in GCC Linker but still get those problem. Thanks a lot for your answer. :)
Here is the correct procedure for setting up the current (as of 7/2/13) GNU bignum libraries with Eclipse CDT, MinGW, and msys for C++. To get through this, you should have used Unix or Linux before, as well as Windows, and you should have a vague recollection of programming and compiling programs. This is the culmination of over a week of research and hardcore frustration, so if I messed something up note it politely or I will blow you up with the power of my mind!
1) I assume you have already downloaded and installed Eclipse and MinGW and have installed msys into MinGW. You must install MinGW before msys!
2) Download the tarball for the GMP libraries from gmplib.org to ${gmp_download}. I downloaded the gmp-5.1.2.tar.xz because I have never used lzip and didn't know if it was available in msys.
3) Open up an msys window (essentially a bash shell). cd ${gmp_buid} and tar -Jxvf ${gmp_download}/gmp-x.x.x.tar.xz
Those tar options are different from what you may find elsewhere on the web! -Jxvf is right for xz (and I think lzip), but for gzip you use -xzvf.
4) cd gmp-x.x.x and run ./config.guess. Write down the output. You will need it next.
5) Run ./configure --prefix=${gmp_build} --build= --enable-cxx --with-gnu-ld
Apparently if you don't explicitly tell GMP to build for your platform it builds everything, which is bad. The cxx option builds the C++ libraries and --with-gnu-ld allows it to work with ld. Pretty straightforward.
6) make
7) make install
EX: suppose you installed to C:/gmp. You should have gmp/include/gmp.h and gmpxx.h. You should also have gmp/lib/libgmp.a, libgmp.la, libgmpxx.a, libgmpxx.la. You should also have a share directory with stuff in it.
8) Set up eclipse:
Go to project --> properties
Under C/C++ build --> Environment edit the PATH variable and add ${gmp_build}/include;${gmp_build}/lib
Under C/C++ build --> settings --> tool settings --> GCC Assembler --> general add ${gmp_build}/include as an include path.
Same place but --> GCC C++ compiler --> Includes add ${gmp_build}/include as an include path.
Same place --> GCC C++ compiler --> Miscellaneous add -lgmp -lgmpxx to the END of the line. THE END OF THE LINE!
Same place --> GCC C compiler Add the same include paths and miscellaneous options as before.
Same place --> MinGW C++ linker --> Libraries Add to the "Libraries (-l)" both gmp and gmpxx IN THAT ORDER! Now add ${gmp_build}/lib to "LIbrary Search Path (-L)"
Under C/C++ General --> Paths & Symbols --> Incudes Tab check that you have ${gmp_build}/include in your include directories for Assembly, C, and C++. If they aren't there you may have messed up an earlier step. They should be auto populated by Eclipse.
Same place --> Libraries Tab check that you have gmp and gmpxx IN THAT ORDER. It should already be populated.
Same Place --> Library Paths Tab Check for ${gmp_build}/lib which should already be there.
Hit "Apply" and make sure you rebuild the index or the changes won't take. Hit OK to close out.
9) Run this short program to verify your setup:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <gmp.h>
#include <gmpxx.h>
using namespace std;
int main ()
{
mpz_t p;
mpz_init_set_ui (p,3);
return 0;
}
Your compile commands should look similar to this:
g++ "-IC:\gmp\include" -O0 -g3 -Wall -c -fmessage-length=0 -lgmp -lgmpxx -o main.o "..\main.cpp" g++ "-LC:\gmp\lib" -o GMPDebug.exe main.o -lgmp -lgmpxx
Notes:
1) The order of the options is important. I don't know all of the whys, but if the second command line (which links the program) has the -lgmp -lgmpxx flags before the -o option, the linking will fail miserably.
2) The -l flag is a tricky one. It actually says "Go look in -L for liblibrary.a". In this case "Go look in C:\gmp\lib for libgmp.a and libgmpxx.a".
3) I have heard of bugs involving cout and the 64 bit version of eclipse, so I am using the 32 bit version, where I am seeing the same bug. :-)