although it's been said that the support for c++0x new features in g++ are in experimental mode, many gcc developer claimed that you can use most of the new features in your codes and get the program to work.
but when I try to compile this simple program it results in segmentation fault. Why?
#include <thread>
#include <iostream>
void my_thread_func()
{
std::cout<<"hello"<<std::endl;
}
int main()
{
std::thread t(my_thread_func);
t.join();
}
g++ -std=c++0x -Wall -o run main.cc
I linked the executable with pthread library and it worked! I did not see any missing shared library dependency (ldd), but seems like std C++ library implementation on Linux uses pthread internally.
g++ thread.cpp -o thread -Wall -std=c++0x -lpthread
Related
When I run the following code,
#include <future>
int main()
{
std::promise<int> p;
p.set_value(1);
return 0;
}
std::system_error is thrown. However, when I set the promise's value in another thread,
#include <future>
#include <thread>
int main()
{
std::promise<int> p;
std::thread([&]{p.set_value(1);}).join();
return 0;
}
everything works fine. From what I understand about std::promise, calling set_value shouldn't throw an exception unless the promise has no shared state (i.e. it's been moved from) or a value has already been assigned to it, and even then it would throw std::future_error, not std::system_error. Since there's no data race or anything of that sort, it shouldn't matter whether I call set_value from the thread in which I created the promise or in another thread. Is there something I'm missing?
I've tried this using both g++ and clang with the same results. Specifically, when I run the code at the top, the following is output to stderr:
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
Aborted (core dumped)
These commands were used to compile the code at the top,
g++ main_thread.cpp -o main_thread -std=c++17 -g -Og
clang main_thread.cpp -o main_thread -std=c++17 -lstdc++
and these were used to compile the code at the bottom:
g++ separate_thread.cpp -o separate_thread -lpthread -std=c++17 -g -Og
clang separate_thread.cpp -o separate_thread -std=c++17 -lstdc++ -lpthread
std::promise is part of the Thread Support Library so it would stand to reason that it requires enabling thread support in your compiler options (e.g. -pthread).
Note that -pthread affects the compilation as well as linkage stages. From man g++:
-pthread
Adds support for multithreading with the pthreads library. This option sets flags for both the preprocessor and linker.
I am creating a C++ library with exported C functions that use some STL functionality. I want to include the this library in a C application.
I have reduced the problem as much as I could to the following 4 files.
main.c
#include "aaa.h"
#include <stdio.h>
int main()
{
printf("Version: %u.%u\n", GetAPIMajorVersion(), GetAPIMinorVersion());
return 0;
}
aaa.h
#ifndef AAA_H
#define AAA_H
#ifdef __cplusplus
#define DllExport extern "C"
#else // __cplusplus
#define DllExport
#endif // __cplusplus
#include <stdint.h>
DllExport uint32_t GetAPIMajorVersion();
DllExport uint32_t GetAPIMinorVersion();
#endif // AAA_H
aaa.cpp
#include "aaa.h"
#include <string>
#include <vector>
// Builds and works fine.
uint32_t GetAPIMajorVersion()
{
std::string val = "hello world";
return val.size();
}
// Produces the error messages
uint32_t GetAPIMinorVersion()
{
std::vector<bool> test;
test.push_back(true);
return test.size();
}
I am using the following script to build the library and the application.
build.sh
# Build the C++ library
g++ -m64 -Wall -O3 -c -fmessage-length=0 -fPIC -MMD -MP aaa.cpp -o aaa.o
ar rcs libaaa.a aaa.o
# Build the executable
gcc -m64 -Wall -static main.c -o main -L./ -laaa
I get the following errors when I try to build the C application
.//libaaa.a(aaa.o): In function `GetAPIMinorVersion':
aaa.cpp:(.text+0xeb): undefined reference to `operator delete(void*)'
aaa.cpp:(.text+0x1c7): undefined reference to `operator delete(void*)'
.//libaaa.a(aaa.o): In function `std::vector<bool, std::allocator<bool> >::_M_insert_aux(std::_Bit_iterator, bool)':
aaa.cpp:(.text._ZNSt6vectorIbSaIbEE13_M_insert_auxESt13_Bit_iteratorb[_ZNSt6vectorIbSaIbEE13_M_insert_auxESt13_Bit_iteratorb]+0x1d8): undefined reference to `operator new(unsigned long)'aaa.cpp:(.text._ZNSt6vectorIbSaIbEE13_M_insert_auxESt13_Bit_iteratorb[_ZNSt6vectorIbSaIbEE13_M_insert_auxESt13_Bit_iteratorb]+0x339): undefined reference to `operator delete(void*)'
aaa.cpp:(.text._ZNSt6vectorIbSaIbEE13_M_insert_auxESt13_Bit_iteratorb[_ZNSt6vectorIbSaIbEE13_M_insert_auxESt13_Bit_iteratorb]+0x3cb): undefined reference to `std::__throw_length_error(char const*)'.//libaaa.a(aaa.o):(.data.DW.ref.__gxx_personality_v0[DW.ref.__gxx_personality_v0]+0x0): undefined reference to `__gxx_personality_v0'
collect2: error: ld returned 1 exit status
I looked into this error and it seems to be because the C application does not have access to the STL libraries but If we alter main.c to only make a call to the GetAPIMajorVersion() and remove the GetAPIMinorVersion() function from the library. The application compiles and runs as expected.
That leads me to believe that the issue is not with the STL library in general but with some of the functions in the STL library.
My next guess is that it is possible that the std::vector<bool>::push_back() function could throw a exception and this is including elements into the aaa.a library that the C application can not find.
If this is the issue then, how do I include the require parts of the STL library in the aaa.a library so it can be used by the C Application?
I have found that if I change the C application to be build with g++ instead of gcc it builds and runs fine. Unfortunately the compiler that I am using in the end only supports C99 and this is not an option for me.
g++ -m64 -Wall -static main.c -o main -L./ -laaa
How should I build this library, that includes STL functions, in a way that the library functions can be called from a C application?
Edit
The compiler that I am using at the end is Arm Keil
There does not seem to be an option to include the stdc++ as a library in the Arm Keil IDE/Compiler. I can't change the command to build the C application to gcc -m64 -Wall -static main.c -o main -L./ -laaa -lstdc++ as far as I am aware.
You could try to build a C++ shared library, linking -lstdc++.
So let -laaa be a shared library libaaa.so (from source files aaa1.cc and aaa2.cc, and having position-independent code) that you would build with:
g++ -fPIC -O3 -g aaa1.cc -o aaa1.pic.o
g++ -fPIC -O3 -g aaa2.cc -o aaa2.pic.o
g++ -fPIC -shared -O3 -g aaa1.pic.o aaa2.pic.o -lstdc++ -o libaaa.so
You might also set some rpath.
Read Program Library HowTo and Drepper's How to write shared libraries
The compiler that I am using at the end is Arm Keil
You'll better use instead some recent version of a GCC cross-compiler (or of Clang one). Either you build that cross-compiler yourself from the source code of GCC 8 (in autumn 2018), or you install some cross-compiler on your Linux distribution. For example, Debian/Sid has gcc-8-arm-linux-gnueabi and gcc-8-arm-linux-gnueabihf
By experience, hardware vendors provide ancient cross-compilers (and are not good in software engineering). That is why I recommend using a recent GCC cross-compiler, on the command line.
And you'll better link your application with g++.
My next guess is that it is possible that the std::vector::push_back() function could throw a exception
Exceptions need some support at the crt0 level (for std::terminate). If your library throws some exception, the main program has to be linked with g++ (if you want a C++ library usable from C, it should not throw exception outside).
However, it is possible, with some care, to build a C++ library usable from gcc-compiled C code. The libgccjit is such a library (but it does not throw exceptions outside).
I can't change the command to build the C application to gcc -m64 -Wall -static main.c -o main -L./ -laaa -lstdc++ as far as I am aware
You surely could. You need to avoid using Arm Kell and use directly the appropriate cross-compiler on the command line (either the one supplied inside it, or preferably a more recent one that you build from GCC source code or Clang one).
Hi have the following example code:
func.h - header file for functions
#include <vector>
#include <tuple>
using std::vector;
using std::tuple;
tuple <double,double> A(vector<int>& n);
func.cpp - function cpp file
#include <iostream>
#include <vector>
#include <tuple>
using namespace std;
tuple <double,double> A(vector<int>& n)
{
double a1=n.size();
double a2=a1+0.5;
return make_tuple(a1,a2);
}
main.cpp - main cpp file
#include <iostream>
#include <vector>
#include <tuple>
#include "func.h"
using namespace std;
int main()
{
double a1,a2;
vector<int> n;
n.push_back(1);
n.push_back(2);
tie(a1,a2)=A(n);
return 0;
}
This compiles well in visual studio.
I have a problem compiling it on Linux (gcc version 4.4.7 20120313 Red Hat 4.4.7-11) with:
g++ -03 -std=c++0x main.cpp func.cpp -lm
It does not compile, I get the following errors:
1. In file included from /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/array:35,from main.cpp:5:/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/c++0x_warning.h:31:2: error: #error This file requires compiler and library suppcoming ISO C++ standard, C++0x. This support is currently experimental, and must be enabled with the -std=c++0x or -std=gnu++0x compiler options.
2. ‘std::tuple’ has not been declared
3. expected constructor, destructor, or type conversion before ‘<’ token
Any guidance on how to deal with this will be helpful!
Surprisingly the error seems to tell you that std=c++0x is not set.
Double check your compilation command. it should be
g++ -std=c++0x -o b main.cpp func.cpp -O3 -lm
and not
g++ -o -std=c++0x b main.cpp func.cpp -03 -lm
as in the original question.
You are telling GCC to output to the file named "-std=c++0x", and thus not setting that option at all, leading to this error. What it does with "b" afterwards, I have no idea. But you should always do "-o outputfilename" and not put other options between the "-o" option and its argument.
I cut and pasted your three files (func.h, func.cpp and main.cpp) and I can assure you that on my Linux box (CentOS 7.2) with g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4) everything works fine (your original command had some errors):
g++ -o myProg -O3 -std=c++0x main.cpp func.cpp -lm
Update your GCC (even from sources if you have several hours ;) ) .
Since you want to run an executable (compiled from recent C++11 or C++14 source code) on a server with an old version of Linux and of GCC -you have GCC 4.4 which does not support recent C++ standards, because it appeared in 2009 before the publication date (2011) of C++11- you could try the following:
install a recent Linux distribution on your own laptop (or computer) and check that its GCC compiler is at least GCC 5 (and preferably GCC 6) by running g++ --version (you might need to use g++-5 instead of g++, etc...)
compile and link statically your program on that laptop using g++ -static -std=c++14 -Wall func.cpp main.cpp -lm -o mybinprog (and perhaps also -O3 if you want to optimize and/or -g for debugging -better do the debugging locally-)
copy (e.g. using scp mybinprog remotehost:) the executable to the remote server and run it there
It is very probable (but not certain) that a statically linked executable built on a newer Linux (laptop) would run on some older Linux server.
BTW, to compile a multi-source file program, better learn how to use GNU make
Notice that order of program arguments to g++ matters a big lot, so read the documentation about Invoking GCC.
PS. Technically you might even try to link dynamically the C library and statically the C++ standard library.
I've had a maddening problem that I need some help with. I'm attempting to write a file finder or parser that finds all of the files of a given format in a directory. I want this to be a class, and I also want it to run in it's own separate thread from main(). I am using Ubuntu 14.04LTS, with it's boost installation (1.54). Here is the vanilla version of my code, just linking against boost::system.
#include <iostream>
#include <thread>
#include <vector>
#include <string>
class fileFinder {
private:
std::string dName;
public:
fileFinder() : dName("") { };
fileFinder(const std::string &dirName) : dName(dirName) { };
void runFileFinder(void) {
std::string fileFinderName = "Hi from filefinder!";
std::cout << fileFinderName << std::endl;
};
};
int main(int argc, char *argv[]) {
//Get the dirname, not safe yet
std::string dirName = argv[1];
fileFinder fFinderThread(dirName);
std::thread t1(&fileFinder::runFileFinder, &fFinderThread);
t1.join();
return EXIT_SUCCESS;
}
When I compile, everything works out great, and the class gets instantiated, and then run in a separate thread. I will link against boost_system just to show that everything is still ok.
> g++ -g -Wall -I/usr/include/boost/ -c rFileFinder.cpp -std=c++11 -pthread
> g++ -g -Wall rFileFinder.o -o rFileFinder -L/usr/lib/x86_64-linux-gnu/ -lboost_system -std=c++11 -pthread
> ./rFileFinder abcd
Hi from filefinder: abcd
Now, since I want to find all the files of a certain type, using boost::filesystem would be awesome. Even attempting to link against the boost::filesystem library produces a runtime threading error (just add -lboost_filesystem to the libraries).
> g++ -g -Wall -I/usr/include/boost/ -c rFileFinder.cpp -std=c++11 -pthread
> g++ -g -Wall rFileFinder.o -o rFileFinder -L/usr/lib/x86_64-linux-gnu/ -lboost_system -lboost_filesystem -std=c++11 -pthread
> ./rFileFinder abcd
terminate called after throwing an instance of 'std::system_error'
what(): Enable multithreading to use std::thread. Operation not permitted
Aborted (core dumped)
And so, this is driving me insane, since I am going to need to have both multithreading capabilities (there is a lot more than just this part of the problem). I've attempted to tease this answer out of the internet, but basically everything I come across is about how the linking to c++11 or pthread isn't done correctly in the compilation and linker steps. Is there a way for me to use both std::thread and boost::filesystem, or am I just hosed?
You need to link to the posix threads library on your system
With gcc or clang, typically this is done by supplying g++ -pthread on the command line.
Technically you should specify to link with the respective dynamic library too
g++ -pthread test.cpp -lboost_system -lboost_thread -lboost_filesystem
Using g++ 4.8, it seems that one cannot have both the -pthread and -std=c++11 flags for the compiler options. They mutually exclude each other on mac (with homebrew gcc48) and on my Ubuntu distro (14.04LTS with g++-4.8). Just use -std=c++11.
I'm using MinGw on Windows 7. The following simple program compiles fine, but the linker complains and I do not understand what's wrong:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
std::vector<int> iv;
iv.push_back(7);
cout << iv.back() << endl;
return 0;
}
the compiler/linker messages look as follows:
mingw32-g++.exe -Wall -fexceptions -std=c++0x -Wall -g -std=c++0x -Wall -g -frepo -IC:\cppbuchincludes\include -IG:\Boost -IG:\Users\thomas\cpp\STLUsage\\include -c G:\Users\thomas\cpp\STLUsage\main.cpp -o obj\Debug\main.o
mingw32-g++.exe -o bin\Debug\STLUsage.exe obj\Debug\main.o G:\Boost\stage\lib\libboost_filesystem-mgw45-mt-d-1_45.dll.a G:\Boost\stage\lib\libboost_regex-mgw45-mt-d-1_45.dll.a G:\Boost\stage\lib\libboost_system-mgw45-mt-d-1_45.dll.a G:\Boost\stage\lib\libboost_thread-mgw45-mt-1_45.dll.a G:\Boost\stage\lib\libboost_unit_test_framework-mgw45-mt-d-1_45.dll.a
collect: recompiling G:\Users\thomas\cpp\STLUsage\main.cpp
collect: relinking
collect2: '_ZNSt12_Vector_baseIiSaIiEEC1Ev' was assigned to 'obj\Debug\main.rpo', but was not defined during recompilation, or vice versa
obj\Debug\main.o: In function `vector':
c:/mingw/bin/../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_vector.h:208: undefined reference to `std::_Vector_base<int, std::allocator<int> >::_Vector_base()'
(...and so on...)
I can use templates I defined myself.
I have that MinGw binary from a book and followed the instructions in that book regarding compiler settings. In particular the references to the Boost libs are taken from there.
This must be a simple thing, I just want to make trivial use of the STL.
Edit following the advice given in an answer, I replaced the binary to be used to compile by g++.exe in the Settings -> Compiler and debugging -> toolchain executables dialog, but I'm getting the same error messages (with mingw32-g++.exe now replaced by g++.exe).
Edit (once more) this has to be problem eith the Code::Blocks settings, since compiling using g++ from the command line works just fine.
Use g++ to compile and link the program. mingw32-g++.exe doesn't do that.
FAQ says,
What's the difference between gcc and mingw32-gcc?
The mingw32-gcc, mingw32-g++, etc. binaries exist as an aid to cross development. They are created in a typical build of gcc. They are therefore distributed as the maintainers of GCC meant them to be. The gcc.exe indicates that the binary produces binaries for a target equal to the build, while the mingw32-gcc binary produces binaries to be executed on the mingw32 target.
So I guess the problem is because of mingw32-g++.exe which you're not supposed to use, for normal build.
Try these:
g++ program.cpp //simple build
g++ program.cpp -Wall //build with all warnings enabled
g++ program.cpp -Wall -O2 //enable warnings and optimization level 2
g++ program.cpp -std=c++0x //use C++11 features
Hope that helps.