Have a strange problem with g++ compiled programs when using the "-static" switch.
I ran into this issue cross compiling executables for embedded ARM systems (though it seems architecture independent). Static linking all the libraries is required for deployment because the libraries are not on the target system. So I need the "-static" switch.
It seems C++ exceptions thrown in a std::thread are not being caught and cause the process to crash. I have narrowed it down to the code below:
#include <thread>
#include <iostream>
void thread_throwing_exception() {
try {
//this is a bad conversion that throws exception
long val = std::stoull("bad");
}
catch (const std::exception& ex) {
std::cerr << "caught exception: " << ex.what() << std::endl;
}
}
int main() {
std::thread thread;
thread = std::thread(thread_throwing_exception);
thread.join();
std::cout << "exiting\n";
return 0;
}
If I build it without the -static switch:
g++- -std=c++11 test.cpp -o test_x64 -g -static-libstdc++ -static-libgcc -pthread
It executes as expected:
./test_x64
caught exception: stoull
exiting
Now with -static switch. (I know it is not required for this program because there are no external libraries, but I need it for my application)
g++ -std=c++11 test.cpp -o test_x64 -g -static-libstdc++ -static-libgcc -pthread -static
Output:
./test_x64
Segmentation fault
Stack trace from gdb:
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff7ff9700 (LWP 13007)]
Thread 1 "test_x64" received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x0000000000401b27 in __gthread_equal (__t1=0, __t2=0) at /usr/include/x86_64-linux-gnu/c++/5/bits/gthr-default.h:680
#2 0x0000000000401eeb in std::operator== (__x=..., __y=...) at /usr/include/c++/5/thread:84
#3 0x0000000000401fb4 in std::thread::joinable (this=0x7fffffffde80) at /usr/include/c++/5/thread:170
#4 0x0000000000401f32 in std::thread::operator=(std::thread&&) (this=0x7fffffffde80,
__t=<unknown type in /media/sf_code/ziposoft/tests/test_bad/test_x64, CU 0x0, DIE 0x7a82>) at /usr/include/c++/5/thread:158
#5 0x0000000000401d28 in main () at test.cpp:33
I have tried g++-5, g++-7, g++-8. Any help would be greatly appreciated.
From doing research, it seems "don't use static linking" is a popular sentiment, but for embedded deployment, static linking is very useful.
Answer is here. Actually had nothing to do with exceptions, I was confusing it with another issue I had.
when g++ static link pthread, cause Segmentation fault, why?
Related
I am trying to link guile to an Rcpp file. It seems like things compile but there is an error when loading:
sourceCpp("test_2.cpp", rebuild = TRUE, showOutput = TRUE)
/usr/lib/R/bin/R CMD SHLIB --preclean -o 'sourceCpp_2.so' 'test_2.cpp'
g++-10 -I"/usr/share/R/include" -DNDEBUG -I"/home/matias/R/x86_64-pc-linux-gnu-library/4.0/Rcpp/include" -I"/home/matias/Documentos/Program/R/guile" -fpic -O3 -march=native -mtune=native -fPIC -pthread -I"/usr/include/guile/3.0" -c test_2.cpp -o test_2.o
g++-10 -shared -L/usr/lib/R/lib -lm -ldl -lgmpxx -lgmp -lmpfr -lmpc -lguile-3.0 -lgc -o sourceCpp_2.so test_2.o -L/usr/lib/R/lib -lR
Error in dyn.load("/tmp/Rtmpm2flY8/sourceCpp-x86_64-pc-linux-gnu-1.0.5/sourcecpp_29e2d33505085/sourceCpp_2.so") :
unable to load shared object '/tmp/Rtmpm2flY8/sourceCpp-x86_64-pc-linux-gnu-1.0.5/sourcecpp_29e2d33505085/sourceCpp_2.so':
/tmp/Rtmpm2flY8/sourceCpp-x86_64-pc-linux-gnu-1.0.5/sourcecpp_29e2d33505085/sourceCpp_2.so: undefined symbol: scm_init_guile
The linking works fine if I remove the Rcpp header and build directly with g++ instead.
My Makevars look like this:
CXX = g++-10
CXXFLAGS = -O3 -march=native -mtune=native -fPIC -pthread -I"/usr/include/guile/3.0"
CXXSTD = -std=c++11
LDFLAGS = -lm -ldl -lgmpxx -lgmp -lmpfr -lmpc -lguile-3.0 -lgc
The .cpp file:
#include <Rcpp.h>
#include <stdio.h>
#include <libguile.h>
using namespace Rcpp;
// [[Rcpp::export]]
int test_guile() {
SCM func, func2;
scm_init_guile();
scm_c_primitive_load("script.scm");
func = scm_variable_ref(scm_c_lookup("simple-func"));
func2 = scm_variable_ref(scm_c_lookup("quick-test"));
scm_call_0(func);
scm_call_0(func2);
return 0;
}
You are so, so close. You essentially solved this. I just took your file, made a small modification of making the script an argument and (as you didn't post script.scm) commented out the content-specific stuff. We still load it though:
#include <Rcpp.h>
#include <stdio.h>
#include <libguile.h>
using namespace Rcpp;
// [[Rcpp::export]]
int test_guile(std::string file) {
SCM func, func2;
scm_init_guile();
scm_c_primitive_load(file.c_str());
//func = scm_variable_ref(scm_c_lookup("simple-func"));
//func2 = scm_variable_ref(scm_c_lookup("quick-test"));
//scm_call_0(func);
//scm_call_0(func2);
return 0;
}
Similarly I just added a src/Makevars to the Rcpp.package.skeleton() created file. This is not good enough to ship as you need some minimal configure or alike logic to get these values from guile-config-3.0 or alike. But it passes the litmus test. C++11 is the default already under R 4.0.*, and the compiler is recent on my box anyway so we just have this (after removing a few GNU GMP and related parts we do not need):
PKG_CXXFLAGS = -I"/usr/include/guile/3.0"
PKG_LIBS = -lguile-3.0 -lgc
This now builds, installs, and runs just fine:
> file <- system.file("guile", "script.scm", package="RcppGuile")
> RcppGuile::test_guile(file)
[1] 0
>
For reference, I committed and pushed the entire example package here. If you provide a pointer to script.scm we can add that too.
Edit: A few seconds of googling leads to the script.scm you may have used so now we have a fully working example with a working embedded Guile interpreter:
> library(RcppGuile)
> test_guile(system.file("guile", "script.scm", package="RcppGuile"))
Script called, now I can change this
Adding another function, can modify without recompilation
Called this, without recompiling the C code
[1] 0
>
I am trying to compile the following code ([cuShiftOr]) to a linux box. Original code is running on Visual Studio 2013 in Windows.
My strategy is to compile all .cu files like below:
nvcc -std=c++11 -Icpp11-range -gencode=arch=compute_52,code=\"sm_52,compute_52\" --use-local-env --cl-version 2013 -maxrregcount=0 --machine 64 --compile -cudart static -DWIN32 -DWIN64 -DNDEBUG -D_CONSOLE -D_MBCS -I$HOME/cuShiftOr/CuShiftOr -I$HOME/cuShiftOr/CuShiftOrBenchmark -I$HOME/cuShiftOr/tinyformat -Xcompiler "-fPIC -fexceptions -ffunction-sections -fdata-sections -fpermissive" -ccbin=/opt/cray/pe/craype/2.5.10/bin/CC -c CuShiftOr/device/hybrid.cu -o objs/CuShiftOr/device/hybrid.cu.o
Likewise for the rest.
At the final stage link everything together by running:
nvcc -std=c++11 -Icpp11-range -gencode=arch=compute_52,code=\"sm_52,compute_52\" --use-local-env --cl-version 2013 -maxrregcount=0 --machine 64 -cudart static -DWIN32 -DWIN64 -DNDEBUG -D_CONSOLE -D_MBCS -I$HOME/cuShiftOr/CuShiftOr -I$HOME/cuShiftOr/CuShiftOrBenchmark -I$HOME/cuShiftOr/tinyformat -Xcompiler "-fPIC -std=c++11 -Icpp11-range -fexceptions -ffunction-sections -fdata-sections -fpermissive -Wnon-template-friend" -ccbin=/opt/cray/pe/craype/2.5.10/bin/CC -o CuShiftOrBenchmark.a objs/CuShiftOr/device/hybrid.cu.o objs/CuShiftOr/util/op.cu.o objs/CuShiftOr/device/segment.cu.o objs/CuShiftOr/host.cu.o objs/CuShiftOr/util/timer.cu.o objs/CuShiftOr/util/file.cu.o objs/CuShiftOr/util/generator.cu.o objs/CuShiftOrBenchmark/kernel.cu.o -lm
However that leads me this undefined reference issue:
objs/CuShiftOrBenchmark/kernel.cu.o: In function `void run_benchmark<unsigned int>(std::ostream&, cushiftor::device::Handler<unsigned int>*, long, unsigned int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
tmpxft_00003ea2_00000000-4_kernel.cudafe1.cpp:(.text._Z13run_benchmarkIjEvRSoPN9cushiftor6device7HandlerIT_EEljiNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_Z13run_benchmarkIjEvRSoPN9cushiftor6device7HandlerIT_EEljiNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x203): undefined reference to `cushiftor::util::op::bit<unsigned int>::size'
collect2: error: ld returned 1 exit status
inside op.cuh it is defined as:
template<typename type>
struct bit {
static const int size = sizeof(type) * 8;
};
template<typename word>
__host__ __device__ __forceinline__ word ones(int m) {
return ~word(0) >> (bit<word>::size - m);
}
and then on kernel.cu we have:
#include "util/op.cuh"
using cushiftor::util::op::bit;
using cushiftor::util::op::bytepack;
using cushiftor::util::op::div_up;
using cushiftor::util::op::round_up;
using cushiftor::util::op::shuffle_up;
Further more compiling with Visual Studio 2013 (which works since the project was made on that) shows some instantiations that I am not sure if g++ is doing e.g:
2>C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(209): warning C4244: 'argument' : conversion from 'int64_t' to 'cushiftor::env::datasize_t', possible loss of data
2> C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(230) : see reference to function template instantiation 'void benchmark_with_file<word>(cushiftor::device::Handler<word> *)' being compiled
2> with
2> [
2> word=unsigned int
2> ]
2>C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(86): warning C4018: '<=' : signed/unsigned mismatch
2> C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(132) : see reference to function template instantiation 'void run_benchmark<word>(std::ostream &,cushiftor::device::Handler<word> *,int64_t,cushiftor::env::datasize_t,int,std::string)' being compiled
2> with
2> [
2> word=unsigned int
2> ]
Now my C++11 template knowledge is very limited but I did try to instantiate also inside the kernel.cu by adding:
template class cushiftor::util::op::bit<unsigned int>;
However to no avail... Any tips are very welcomed!
I believe this question is essentially a duplicate of this one. However simply marking it as such with no explanation may be a bit obscure. Therefore I'm going to provide a CW answer in the hopes that someone may improve it or correct me if I am wrong.
A possible MCVE derived from the code is as follows (note that I'm converting to using g++ directly rather than nvcc, as the manifestation and workarounds are the same):
$ cat test.cpp
#include <iostream>
namespace cushiftor {
namespace util {
namespace op {
template<typename type>
struct bit {
static const int size = sizeof(type) * 8;
};
}
}
}
#ifdef FIX2
void f(const int data){
#else
void f(const int &data){
#endif
std::cout << "size of type in bits is: " << data << std::endl;
}
using cushiftor::util::op::bit;
#ifdef FIX1
template <typename T> const int bit<T>::size;
#endif
template<typename word>
void run_benchmark() {
f(bit<word>::size);
}
int main(){
run_benchmark<unsigned>();
}
$ g++ -o test test.cpp
/tmp/ccCW51e3.o: In function `void run_benchmark<unsigned int>()':
test.cpp:(.text._Z13run_benchmarkIjEvv[_Z13run_benchmarkIjEvv]+0x5): undefined reference to `cushiftor::util::op::bit<unsigned int>::size'
collect2: error: ld returned 1 exit status
$ g++ -DFIX1 -o test test.cpp
$ g++ -DFIX2 -o test test.cpp
$
This MCVE was created based on inspection of relevant code in kernel.cu, tinyformat.h, and op.cuh, in the original cuShiftOr project (and paper).
We see that if we compile the code as-is, it generates a similar error to that reported in the question.
Compiling with -DFIX2 demonstrates that taking the item in question (bit::size) as a reference argument is essential to witnessing of the issue.
Compiling with -DFIX1 eliminates the issue, and I believe is the correct approach in this case.
The explanation for this issue seems to be that the compiler may treat the static const member as a compile-time constant, unless it is "used" in the code. ("Used" has a special language-specific meaning here.) If it is "used" in the code, then the compiler must be able to take the address of it (sensible in the case of a reference parameter) and to take the address of it, the class/struct definition is not sufficient. (It is apparently only a declaration even though it appears in the class/struct definition. The declaration is sufficient for usage equivalently to a compile-time constant, but is not sufficient for the case where we wish to take the address of it.)
From here:
If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19) In that case, the member can appear in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program
I believe the FIX1 code modification satisfies the bolded requirement above.
With the above preamble, I believe it is valid to mark this as a duplicate.
With respect to the behavior of the original project on windows, I would conjecture that compilers may have leeway in enforcement of this, and may in fact provide referenceable member symbols even when the program does not explicitly define them.
Hy,
while using the libxml++-2.36-library for my code I found out, that this library produces a "double free or corruption"-error, when exceptions of the basetype std::exception are thrown in the sax-parser-callbacks. (e.g. on_start_document, on_end_document, on_...)
But it behaves normally, this means, that the exception can be catched, if an exception of basetype xmlpp::exception is thrown.
Interestingly xmlpp::exception is based on std::exception.
To verify this, I have created a MWE:
#include <libxml++/libxml++.h>
#include <iostream>
class xml_parser : public xmlpp::SaxParser {
protected:
virtual void on_start_document() override;
};
void xml_parser::on_start_document() {
throw std::runtime_error("test-exception");
//throw xmlpp::internal_error("test-exception");
}
int main(void) {
xml_parser parser;
try {
parser.parse_memory(
u8"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
} catch (std::exception &e) {
std::cerr << "Caught exception: " << e.what() << std::endl;
}
}
It can be compiled by:
g++ main.cpp -o main `pkg-config --cflags --libs libxml++-2.6` -Wall -pedantic -Wextra -Werror -Wcast-qual -Wcast-align -Wconversion -fdiagnostics-color=auto -g -O2 -std=c++11
If I execute the file as it is, I get the following output:
*** Error in `./main': double free or corruption (!prev): 0x0000000000b35b30 ***
If I uncomment the second line and comment the first line of the on_start_document(), I get the following output:
Caught exception: test-exception
Compiler: g++ 4.9.2
libxml++: 2.6 - 2.36
Is there a way, to get std::exception based exceptions working, without creating special xmlpp::exception-Based Exceptions?
What's happening is that an _xmlSAXHandler object is being freed twice, once by delete and another by xmlFree(). This can be seen by setting a break point on the appropriate free() standard libc call. For example, on an Ubuntu 'trusty' machine, I set a breakpoint on _int_free and saw that the same pointer was being freed twice:
Breakpoint 2, _int_free (av=0x7ffff741f760 , p=0x610b80,
have_lock=0) at malloc.c:3814
3814 in malloc.c
(gdb) bt
#0 _int_free (av=0x7ffff741f760 , p=0x610b80, have_lock=0)
at malloc.c:3814
#1 0x00007ffff6d32a59 in xmlFreeParserCtxt ()
from /usr/lib/x86_64-linux-gnu/libxml2.so.2
#2 0x00007ffff7bc6be2 in xmlpp::Parser::release_underlying (
this=this#entry=0x7fffffffdd30) at libxml++/parsers/parser.cc:162
#3 0x00007ffff7bcc665 in xmlpp::SaxParser::release_underlying (
this=this#entry=0x7fffffffdd30) at libxml++/parsers/saxparser.cc:329
#4 0x00007ffff7bcc68c in xmlpp::SaxParser::~SaxParser (this=0x7fffffffdd30,
__in_chrg=) at libxml++/parsers/saxparser.cc:83
#5 0x0000000000401d80 in ~xml_parser (this=0x7fffffffdd30,
__in_chrg=) at so31969961_libxmlpp_double_free.cpp:7
#6 main () at so31969961_libxmlpp_double_free.cpp:24
...
Breakpoint 2, _int_free (av=0x7ffff741f760 , p=0x610b80,
have_lock=0) at malloc.c:3814
3814 in malloc.c
(gdb) bt
#0 _int_free (av=0x7ffff741f760 , p=0x610b80, have_lock=0)
at malloc.c:3814
#1 0x00007ffff7bcc69e in ~auto_ptr (this=0x7fffffffdd60,
__in_chrg=) at /usr/include/c++/4.8/backward/auto_ptr.h:170
#2 xmlpp::SaxParser::~SaxParser (this=0x7fffffffdd30,
__in_chrg=) at libxml++/parsers/saxparser.cc:81
#3 0x0000000000401d80 in ~xml_parser (this=0x7fffffffdd30,
__in_chrg=) at so31969961_libxmlpp_double_free.cpp:7
#4 main () at so31969961_libxmlpp_double_free.cpp:24
In this case, 0x610b80 corresponds to the _xmlSAXHandler object held by the SaxParser in its sax_handler_ auto_ptr member. It is first freed by libxml2's xmlFreeParserCtxt() routine. It is then deleted by the std::auto_ptr<_xmlSAXHandler> destructor.
If you look at the source of libxml++'s SaxParser class, in saxparser.cc, you will see that there are several try..catch statements. However, only const exception& is caught. This const exception is not std::exception but rather xmlpp::exception.
When you throw a std::runtime_error in the on_start_document() handler, it is not caught by SaxParserCallback::start_document(). Consequently, as the stack is unwound, the code in SaxParser::parse() that restores the original _xmlSAXHandler pointer in the _xmlParserCtxt is skipped.
The takeaway from this is that you should only throw exceptions deriving from xmlpp::exception within the SaxParser handler methods.
UPDATE: https://bugzilla.gnome.org/show_bug.cgi?id=753570
UPDATE2: Fixed in version 2.39.2.
std::defaultfloat doesn't seem to be defined in GCC, despite being in the standard (I think it's §27.5.6.4). I've isolated it to this simple program:
// test.cpp
#include <iostream>
int main()
{
std::cout << std::defaultfloat << 1.3;
return 0;
}
This compiles in VC++11. I tried compiling this with g++ 4.7.2 and g++ 4.9.0 using both of these commands:
g++ test.cpp
g++ test.cpp -std=c++11
I also tried an online compile on GCC 4.8.1 here, always with the same result:
user#office-debian:~/Documents/test$ g++ test.cpp -std=c++11
test.cpp: In function ‘int main()’:
test.cpp:5:15: error: ‘defaultfloat’ is not a member of ‘std’
std::cout << std::defaultfloat << 1.3;
Why am I getting this error?
GCC libstdc++ just doesn't support these C++11 manipulators in any of
the versions you've compiled against. A patch was submitted exactly one month ago
Having trouble compiling the following C++ code on Windows 7:
#include <boost/asio.hpp>
#include <iostream>
void handler1(const boost::system::error_code &ec)
{
std::cout << "5 s." << std::endl;
}
void handler2(const boost::system::error_code &ec)
{
std::cout << "10 s." << std::endl;
}
int main()
{
boost::asio::io_service io_service;
boost::asio::deadline_timer timer1(io_service, boost::posix_time::seconds(5));
timer1.async_wait(handler1);
boost::asio::deadline_timer timer2(io_service, boost::posix_time::seconds(10));
timer2.async_wait(handler2);
io_service.run();
}
I have MinGW installed (gcc 4.8.1) in c:\mingw with my PATH set up correctly. I have downloaded boost and declared environment variable BOOST_ROOT to be the path where it resides. I have gone through the bootstrap and b2 procedure for boost. I now try and compile:
c:\path\to\sandbox> g++ -I%BOOST_ROOT% -o main main.cpp
Gives a bunch of error: '::UnregisterWaitEx' has not been declared errors
I then search a bit and see I may need to link boost_system. So:
c:\path\to\sandbox> g++ -I%BOOST_ROOT% -lboost_system -o main main.cpp
Same errors. Thought I'd try specify library path. Did a search for boost_system and found static libs (libboost_system-mgw48-mt-1_55.a) in %BOOST_ROOT%/stage/lib. So
c:\path\to\sandbox> g++ -I%BOOST_ROOT% -L%BOOST_ROOT%/stage/lib -lboost_system-mgw48-mt-1_55 -o main main.cpp
Same errors. So I search again and see others suggesting appending a -D-D_WIN32_WINNT=0x0601. So
c:\path\to\sandbox> g++ -I%BOOST_ROOT% -L%BOOST_ROOT%/stage/lib -lboost_system-mgw48-mt-1_55 -o main main.cpp -D_WIN32_WINNT=0x0601
And the inevitable errors:
c:\mingw\include\mswsock.h:125:20: error: 'WSAPOLLFD' was not declared in this scope
int WSAAPI WSAPoll(WSAPOLLFD, ULONG, INT);
^
c:\mingw\include\mswsock.h:125:36: error: expected primary-expression before ',' token
int WSAAPI WSAPoll(WSAPOLLFD, ULONG, INT);
^
c:\mingw\include\mswsock.h:125:41: error: expected primary-expression before ')' token
int WSAAPI WSAPoll(WSAPOLLFD, ULONG, INT);
^
c:\mingw\include\mswsock.h:125:41: error: expression list treated as compound expression in initializer [-fpermissive]
Where am I going wrong?
I went ahead and rebuilt Boost again with b2 toolset=gcc --build-type=complete. Same thing happened. Finally, after all that, it turned out all I needed was to put the linking at the end of the command:
C:\path\to\sandbox> g++ -D_WIN32_WINNT=0x0601 -I%BOOST_ROOT% -L%BOOST_ROOT%\stage\lib -o boosttest boosttest.cpp -lwsock32 -lws2_32 -lboost_system-mgw48-mt-d-1_55
C:\path\to\sandbox> boosttest.exe
5 s.
10 s.
The -D_WIN32_WINNT was still necessary and, for anyone who has skipped the other comments, I had to patch winsock.h as detailed http://sourceforge.net/p/mingw/bugs/1980/. And remember to put %BOOST_ROOT%\stage\lib in your PATH so Windows can find the dll at runtime.
Arduous