I picked up the following demo off the web from https://computing.llnl.gov/tutorials/pthreads/
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
But when I compile it on my machine (running Ubuntu Linux 9.04) I get the following error:
corey#ubuntu:~/demo$ gcc -o term term.c
term.c: In function ‘main’:
term.c:23: warning: incompatible implicit declaration of built-in function ‘exit’
/tmp/cc8BMzwx.o: In function `main':
term.c:(.text+0x82): undefined reference to `pthread_create'
collect2: ld returned 1 exit status
This doesn't make any sense to me, because the header includes pthread.h, which should have the pthread_create function. Any ideas what's going wrong?
For Linux the correct command is:
gcc -pthread -o term term.c
In general, libraries should follow sources and objects on command line, and -lpthread is not an "option", it's a library specification. On a system with only libpthread.a installed,
gcc -lpthread ...
will fail to link.
Read this or this detailed explanation.
For Linux the correct command is:
gcc -o term term.c -lpthread
you have to put -lpthread just after the compile command,this command will tell to the compiler to execute program with pthread.h library.
gcc -l links with a library file.Link -l with library name without the lib prefix.
in eclipse
properties->c/c++Build->setting->GCC C++ linker->libraries in top part add "pthread"
Running from the Linux terminal, what worked for me was compiling using the following command (suppose the c file I want to compile is called test.c):
gcc -o test test.c -pthread
Hope it helps somebody!
If you are using cmake, you can use:
add_compile_options(-pthread)
Or
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
I believe the proper way of adding pthread in CMake is with the following
find_package (Threads REQUIRED)
target_link_libraries(helloworld
${CMAKE_THREAD_LIBS_INIT}
)
Acutally, it gives several examples of compile commands used for pthreads codes are listed in the table below, if you continue reading the following tutorial:
https://computing.llnl.gov/tutorials/pthreads/#Compiling
Compile it like this : gcc demo.c -o demo -pthread
In Visual Studio 2019 specify -pthread in the property pages for the project under:
Linker -> Command Line -> Additional Options
Type in -pthread in the textbox.
You need to use the option -lpthread with gcc.
you need only Add "pthread" in proprieties=>C/C++ build=>GCC C++ Linker=>Libraries=> top part "Libraries(-l)".
thats it
check man page and you will get.
Compile and link with -pthread.
SYNOPSIS
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Compile and link with -pthread.
....
Since none of the answers exactly covered my need (using MSVS Code), I add here my experience with this IDE and CMAKE build tools too.
Step 1: Make sure in your .cpp, (or .hpp if needed) you have included:
#include <functional>
Step 2 For MSVSCode IDE users:
Add this line to your c_cpp_properties.json file:
"compilerArgs": ["-pthread"],
Step 2 For CMAKE build tools users:
Add this line to your CMakeLists.txt
set(CMAKE_CXX_FLAGS "-pthread")
Note: Adding flag -lpthread (instead of -pthread) results in failed linking.
From man gcc,
-pthread
Define additional macros required for using the POSIX threads library.
You should use this option consistently for both compilation and linking.
This option is supported on GNU/Linux targets,
most other Unix derivatives,
and also on x86 Cygwin and MinGW targets.
It is correct that -pthread is an option and the best way to handle this.
There are statements in some answers that it generates different compiled code. This is misleading.
If you wish to duplicate -pthread, you could use -lpthread -D_REENTRANT=1. So there are two things going on with the -pthread option.
Indeed it links with the pthread library as many answers express. Also, the order of the pthread library is important because it may override some weak symbols. So a correct version using -lpthread may need to have it multiple times on the command line.
The other important part is the _REENTRANT define. Note, that this is in the implementation namespace. Some people may care for portability and other not. However, it is very important that it is defined as the first thing in the compilation unit. This symbol will alter the way that many system headers files are parsed.
You can include #define _REENTRANT 1 at the top of every source file, but it is much easier to have it on the command line. Again, the -pthread is the best way to achieve this. Also, gcc may change the way this is implemented in the future. However, I think it is important for programmers to understand what is going on.
term.c: In function ‘main’: term.c:23: warning: incompatible implicit
declaration of built-in function ‘exit’
You never included <stdlib.h>, where exit() is declared. Also, I think newer versions of gcc have removed the need for _REENTRANT.
Why features.h?
Example on godbolt, without -pthread.
So, it is NOT generating different code. Ie, the backend of the compiler is NOT different. It is only conditional compilation and linking to different libraries. It does not generate 'lock free' code or add appropriate machine barriers because you have used this option.
In Anjuta, go to the Build menu, then Configure Project.
In the Configure Options box, add:
LDFLAGS='-lpthread'
Hope it'll help somebody too...
Sometimes, if you use multiple library, check the library dependency.
(e.g. -lpthread -lSDL... <==> ... -lSDL -lpthread)
What does -lm option do in g++ and when is it needed?
Is there a complete description of g++ options?
That's a linker option. It tells the linker to link with (-l) the m library (libm.so/dll). That's the math library. You often need it if you #include <math.h>.
The option does nothing for g++: referring to this answer https://stackoverflow.com/a/1033940/1143274 libstdc++ requires libm, so it will always be linked by g++.
However, there is also some sort of an automatic linking behaviour for gcc, investigated on this thread http://www.linuxforums.org/forum/programming-scripting/125526-c-gcc-math-h-lm.html which I can't seem to find an answer as to where that comes from and which libraries it applies to...
I am porting some code to OpenBSD 5.0 and I ran into this very strange problem.
My build settings use -isystem /usr/local/include. It is hard to remember but I believe I did that to avoid masses of compiler warnings from my use of -Wall on system types -- like BSD -- that install Boost to /usr/local/include. This seems to work great on FreeBSD.
So take the following program:
#include <boost/array.hpp>
int main()
{
return 0;
}
Then build it with:
c++ -O2 -pipe -isystem /usr/local/include -std=c++98 -o test test.cxx
On OpenBSD I discovered that I get:
In file included from /usr/include/g++/string:46,
from /usr/include/g++/stdexcept:44,
from /usr/local/include/boost/array.hpp:35,
from test.cxx:1:
/usr/include/g++/bits/stringfwd.h:48: error: template with C linkage
And it only gets worse from there.
I discovered that I can change the error messages by doing things such as:
#include <stdexcept>
But that only pushes the problem farther back. It is as if the compiler is wrapping every include file inside an extern "C" block.
So far, the only working method seems to be to change back to using -I /usr/local/include and accept the noise from -Wall -W.
The question is, why did OpenBSD do this? It has to be some kind of custom hack to GCC to treat system includes this way.
Recently came across the same issue when working with a freestanding cross compiler.
It seems G++ will do this when targeting "old" systems as indicated here:
http://tigcc.ticalc.org/doc/cpp.html#SEC9a
On very old systems, some of the pre-defined system header directories get even more special treatment. GNU C++ considers code in headers found in those directories to be surrounded by an extern "C" block. There is no way to request this behavior with a #pragma, or from the command line.
Hope this may provide some insight to future travelers here.
I have the following problem. I write a shared library
#include <stdio.h>
#include <stdlib.h>
static void __attribute__ ((constructor)) test_init(void);
static void __attribute__ ((destructor)) test_clean(void);
/* Initialization */
static void test_init(void){
fprintf(stderr,"initialized\n");
fflush(stderr);
}
/* CleanUp */
static void test_clean(void){
fprintf(stderr,"cleaned up\n");
fflush(stderr);
}
double test (double x){
return 2.0*x;
}
And compile it using
gcc -c -fPIC testlib.c -o testlib.o
ld -shared -o libtest.so testlib.o
Then I include it into a test program
#include <stdio.h>
#include <stdlib.h>
extern double test(double x);
void main(void){
printf("%.10e\n",test(10.0));
}
which I compile and start using
gcc testprog.c -o testprog -L. -ltest
LD_LIBRARY_PATH=. ./testprog
Then the output is given by
2.0000000000e+01
which means that the constructor/destructor are not executed. On the other hand, if I compile
ar rvs testlib.a testlib.o
gcc testprog.c testlib.a -o testprog
the output of the program is given by
testprog
initialized
2.0000000000e+01
cleaned up
Why are the constructors not executed if the library is linked dynamically?
I use the following versions
GNU ld (GNU Binutils; openSUSE 11.3) 2.20.0.20100122-6
gcc version 4.5.0 20100604 [gcc-4_5-branch revision 160292] (SUSE Linux)
Thank you in advance for your help!
Edited: 2011-04-13, 11:05
Thank you very much luxifer,
the document helped indirectly! The magic hint was that one should involve the linker through the compiler...
gcc -fPIC testlib.c -shared
-Wl,-soname,libtest.so -o libtest.so
works!!!
Gcc's constructor handling is not the same thing as the ELF constructor handling, rather, it sits on top of it. To work, you need to link in the glue code that is provided in gcc's startup files.
The easiest way to do that is to link using gcc:
gcc -shared -o testlib.so testlib.o
This text is meant for reference, but I'm coming over to your office for convenience :)
I'm not an expert on that field but a quick Google search gave me this. Reading just the beginning of the document and if I get it right the problem is this:
Linked statically your program is self-contained at execution time... it has the whole library in it and it's completely loaded into memory when you run it.
Linked dynamically when the library function is called from your program at execution time the linker tries to resolve all unresolved references on functions by looking if it has an implementation in some library. If so it loads this implementation, i.e. just the functions code.
So if I get this right and the dynamic linker just loads portions of libraries, i.e. needed functions, and not the whole library then this would explain why your constructor isn't called when your library is linked dynamically.
I have to build a "proof of concept" using cgicc on Windows. But currently I am unable to build cgicc. The current release of cgicc v3.2.9 won't build neither in MinGW (gcc v4.5.0 / v3.4.5) nor Cygwin (gcc v4.3.4-3).
By using gcc v3.4.5 and automake in MinGW I got:
HTMLAttributeList.cpp:51: internal compiler error: in rest_of_handle_final, at toplev.c:2067
Please submit a full bug report, with preprocessed source if appropriate.
Using gcc v4.3.4 and automake gives for Cygwin:
In file included from CgiEnvironment.cpp:36:
../cgicc/CgiEnvironment.h:52: error: explicit instantiation of 'class std::vector<cgicc::HTTPCookie, std::allocator<cgicc::HTTPCookie> >' in namespace 'cgicc'
which does not enclose namespace 'std')
and for gcc v4.5.0 in MinGW:
../cgicc/CgiEnvironment.h:52:33: error: explicit instantiation of 'class std::vector<cgicc::HTTPCookie>' in namespace 'cgicc' (which does not enclose namespace
'std')
I tried to ignore the Automake and Autoconf scripts. I set up Eclipse-CDT for using the apropriate compiler switches (I also tried Code::Blocks):
-DHAVE_CONFIG_H -DWIN32 -I.. -Wall -W -pedantic -g -DDLL_EXPORT -DPIC -DCGICC_EXPORTS
But again I got:
explicit instantiation of 'class std::vector<cgicc::HTTPCookie, std::allocator<cgicc::HTTPCookie> >' in namespace 'cgicc' (which does not enclose namespace 'std') CgiEnvironment.h /cgicc/cgicc line 52
CgiEnvironment.h:51 to line 53 contains the ifdef WIN32:
#include <string>
#include <vector>
#include <cstdlib>
namespace cgicc {
...
#ifdef WIN32
template class CGICC_API std::vector<HTTPCookie>;
#endif
...
}
What goes wrong? Any suggestions?
Now I can compile cgicc. Thanks to a very good friend of mine, Vlad Lazarenko and some hours of investigation. But I have to do some major changes.
My friend helped me to go on the right way by understanding the main issue. He and Vlad Lazarenko gave me a good direction to investigate the __declspec(). This is a feature of Microsoft compilers which are now supported in gcc.
During investigation I stumbled over a post with migration hints for GCC3.4.3 to GCC4.1.2. So I moved the explicit instantiation of the templates behind the declared namespace in following headers:
Cgicc.h
CgiEnvironment.h
HTMLAttributeList.h
HTMLElementList.h
Next I discovered a strange behaviour while checking different compiler switches and other things regarding my build environment. During investigatiopn of cgicc header files the defined -DCGICC_EXPORTS becomes sometimes undefined (expansion is shown by Eclipse CDT). So I changed CgiDefs.h from:
// export library symbols
#ifdef CGICC_EXPORTS
# define CGICC_API __declspec(dllexport)
#else
# define CGICC_API __declspec(dllimport)
#endif
to
# define CGICC_API __declspec(dllimport)
At the end I changed the compiler switches to
-DWIN32 -DCGICC_EXPORTS -DHAVE_CONFIG_H -I.. -O0 -g3 -Wall -c -fmessage-length=0 -std=gnu++98. Most important is -std=gnu++98. Without gnu extensions __declspec() wont generate any symbols - even for a static library. I do not understand why I need that for a static library because the symbols should be in their object files which are packet into libcgicc.a.
Now some further questions:
Do anyone know a mechanism how CGICC_EXPORTS can became undefined
without #undef CGICC_EXPORTS and without -UCGICC_EXPORTS?
Why I have to use gnu extensions? I thought the defaults are independend.
Why do I have to use __declspec(dllexport) for a static library?
Why it is not enough to use the object files of a static library? Let me ask the same
in a different way: Why are no symbols found if I try to link object files of a static
library?
What is the advantage/disadvantage of "implicit template instantiation and vague
linkage" versus "explicit template instantiation"?
The CGICC_API should be either defined as __declspec(dllimport) or __declspec(dllexport).
It looks like that DLL_EXPORT macro that gets defined in command line should affect that, but it doesn't.
My guess is that some header handling it is not included. See this and that for more information.