I am trying to make sense of a program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
int main(int argc, char** argv) {
volatile double fShared = 0.0;
// create pthread structures - one for each thread
pthread_t t0;
pthread_t t1;
//Arbitrary pointer variables - void* is a pointer to anything
void *thread_res0;
void *thread_res1;
int res0,res1;
//create a new thread AND run each function
// we pass the ADDRESS of the thread structure as the first argument
// we pass a function name as the third argument - this is known as a FUNCTION pointer
// you might want to look at the man pages for pthread_create
res0 = pthread_create(&t0, NULL, do_this, (void*)"");
res1 = pthread_create(&t1, NULL, do_that, (void*)"");
// Two threads are now running independently of each other and this main function
// the function main is said to run in the main thread, so we are actually running
// The main code can now continue while the threads run - so we can simply block
res0 = pthread_join(t0, &thread_res0);
res1 = pthread_join(t1, &thread_res1);
printf ("\n\nFinal result is fShared = %f\n",fShared);
return (EXIT_SUCCESS);
}
It should be noted that do_this and do_that are functions created earlier in the program. I am getting the following errors:
seed#ubuntu:~/Programs$ Homework2OS.c
/tmp/cceiRtg8.O: in function 'main'
Undefined reference to 'pthread_create'
Undefined reference to 'pthread_create'
Undefined reference to 'pthread_join'
Undefined reference to 'pthread_join'
We were given this bit of code to fix. I have found elsewhere the format for the pthread_create constructor. Do I need to actually define it above the main? I was under the impression it was imported with the library.
I would also venture to guess that it has something to do with the fourth parameter? I understand that the first parameter is the location of the thread (defined above), the second is NULLed, the third is the function call but I do not quite understand what the fourth parameter is supposed to be.
What's wrong?
all the code imports is the header for the pthread library. (pthread.h)
What is missing is the linker needs to actually include the library for gcc the parameter -pthread is needed (AT THE END of the list of parameters to gcc.)
It needs to be at the end because the linker processes parameters in the order given on the command line and if the object files are not already processed, then there will not be any unresolved references for the linker to try to resolve via browsing the pthread library.
I.E. this is wrong:
gcc -g -o myprogram -lpthread myprogram.o
This is correct:
gcc -g -o myprogram myprogram.o -lpthread
Related
I have been trying to implement a small simulation to understand memory allocation of malloc(). I created a shared library called mem.c. I am linking the library to the main but cannot pass the correct address of the simulated "heap". Heap is created by a malloc() call in the shared library.
Address in the shared library: 0x55ddaff662a0
Address in the main: 0xffffffffaff662a0
Only last 4 bytes seem to be correct. Rest is set to 0xf.
However, when I #include "mem.c" in the main it works correctly. How can I achieve the same result without including the mem.c. I am trying to solve this without including mem.c or mem.h. I create shared library as this:
gcc -c -fpic mem.c
gcc -shared -o libmem.so mem.o
gcc main.c -lmem -L. -o main
From your comments
I am trying to implement without using #include mem.h or mem.c.
Then you must provide by other means a prototype for the function you're calling. Without an explicit function prototype, following the tradition of K&R and then later ANSI C, undeclared functions are assumed to return an int and take parameters of type int.
EDIT: Essentially you need to write what'd you normally find in a header, somewhere before you make first use of the function. Or of it's a function pointer you need an appropriate variable to store the function pointer.
For example to declare a function that returns an untyped pointer, and an arbitrary, unspecified number of arguments you'd write
void *getAddr();
Note that using the extern keyword here is not required, since extern linkage is always implied for non-static function declarations.
In case you want to dynamically link at runtime (using dlopen / LoadLibrary → dlsym / GetProcAddress), you'd define a function pointer variable
void* (*getAddr_fptr)();
You can set it using dlsym with
*(void**)(&getAddr_fptr) = dlsym(…)
This awkward way of writing it comes due to function pointers being allowed to have a different size and alignment as data pointers (see the dlsym manpage for details).
These days on the majority of platforms int is a 4 byte type and the most common calling convention pass the first few function arguments by register. On x86 (and x86_64) the registers are AX, BX, CX and DX and may be accessed in different sizes, but may read and write with different size (to allow size conversion). This explains why only the first 4 bytes are passed: It's passed via register and only the write to the register is done as a 4 byte wide write. When the function then reads from the register, it does so with a wider type, with the higher value bits set to all 1.
From the comments:
Do you have a declaration for getAddr in your main code?
No I don't have but I am trying to implement without a declaration, is it possible?
Then that's your problem. Without a declaration, the compiler falls back to a default declaration of int getAddr(). This is incompatible with the actual definition which returns a void *, and calling a function through an incompatible declaration triggers undefined behavior.
What probably happened is that when the return value of the function was actually returned you only got back the 4 low-order bytes. Assuming your system is little-endian, and int is 4 bytes, and a void * is 8 bytes, this would explain the low bits being the same.
You must include a valid declaration before the function is called. It doesn't necessarily have to reside in a header file, but it has to be visible at the point the call happens.
I'm assuming you're trying to accomplish something like this? For mem.c
#include <stdlib.h>
#include <stdio.h>
void* getAddr() {
char *heap = (char *)malloc(10);
printf("%p\n", (void*)heap);
return heap;
}
And then without including any headers for the mem.c functions, you'd probably create a library out of mem.c as you've already mentioned in the question and have something as follows in main.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
typedef void* (*getAddr)(); //prototype for getAddr() in mem.c
int main() {
void* handle = dlopen("./libmem.so", RTLD_LAZY);
if(handle) {
void* fn = dlsym(handle, "getAddr");
if(fn) {
void* addr = ((getAddr)(fn))();
printf("%p\n", addr);
free(addr);
addr = NULL;
} else {
printf("Failed to dlsym %s\n", dlerror());
}
} else {
printf("Failed to dlopen %s\n", dlerror());
}
}
EDIT: For OP's purpose as #Zilog80 mentioned, since the library is being linked with main executable, the dlopen() part can be gotten rid of and main.c can be simplified as
#include <stdio.h>
#include <stdlib.h>
extern void* getAddr(); //prototype for getAddr() in mem.c
int main() {
void* addr = getAddr();
printf("%p\n", addr);
free(addr);
addr = NULL;
}
And used similar compilation commands as OP i.e.
gcc -shared -o libmem.so -fpic mem.c
gcc main.c -lmem -L . -o main
while executing
LD_LIBRARY_PATH=. ./main
I'm trying to compile third party source code using gcc 4.8 on Ubuntu Linux (12.04 x64) with a lot of utilities and test applications where executable entry point is not called main. Don't ask me why - I don't know the answer.
Linker of course complains:
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
Is it possible to force linker to use another method as the entry point? I tried to use these linker options with gcc but neither of them worked:
-Wl,-eWhatever or -Wl,--entry=Whatever or -Wl,-e,Whatever. All ended with the same error.
As by C Standard, the hosted environment (that I guess is your case as/if you want to use standard library headers*) forces you to keep with main function. From C11 §5.1.2.2.1/p1 (emphasis mine):
The function called at program startup is named main. The
implementation declares no prototype for this function. It shall be
defined with a return type of int and with no parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as
argc and argv, though any names may be used, as they are local to the
function in which they are declared):
int main(int argc, char *argv[]) { /* ... */ }
or equivalent;10) or in some other
implementation-defined manner.
There are two options that I can think of to bypass main function requirement in your situation:
Create separate object file (that is, by gcc -c) with main symbol, that just (declares and) calls (i.e. wraps) your custom entry point (possibly passing through argc and argv invocation arguments). This would make linker happy and is as simple as adding single makefile rule.
Compile your program as gcc -DWhatever=main. This essentially replaces every instance of Whatever preprocessing token by main, so linker thinks of Whatever as "proper" main function.
* some headers must be available in freestanding environment too, such as <stddef.h> and <float.h>, see §4/p6 for full list of them.
Here is some basic ilustration of both options. Each assumes, that foo.c is as following:
foo.c
#include <stdio.h>
void foo(void)
{
printf("foo\n");
}
First method:
main.c
/* declare an entry point */
void foo(void);
/* define main as wrapper function */
int main(void)
{
foo();
return 0;
}
Compile & run:
$ gcc -c main.c
$ gcc foo.c main.o
$ ./a.out
foo
Second method:
$ gcc -Dfoo=main foo.c
$ ./a.out
foo
Some things may require more tweaking, but I hope you catch the idea.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
undefined reference to pthread_create in linux (c programming)
I am trying to implement Thread chain in Ubuntu in C. When I compile the following code, I get the errors of Undefined reference to these thread library function even though I have added the header file.I am also getting segmentation fault error. Why is that? I am not accessing some uninitialized memory anywhere in program. Here is the code:
#include <stdio.h>
#include<stdlib.h>
#include <pthread.h>
void* CreateChain(int*);
int main()
{
int num;
pthread_t tid;
scanf("Enter the number of threads to create\n %d",&num);
pthread_create(&tid,NULL,CreateChain,&num);
pthread_join(tid,NULL);
printf("Thread No. %d is terminated\n",num);
return 0;
}
void* CreateChain(int* num )
{
pthread_t tid;
if(num>0)
{
pthread(&tid,NULL,CreateChain,num);
pthread_join(tid,NULL);
printf("Thread No. %d is terminated\n",*num);
}
else
return NULL;
return NULL;
}
I am getting following warnings and the Scanf prompt is not appearing for some reason.
Regards
The pthread.h header file provides a forward declaration of pthread functions. This tells the compiler than these functions exist and have a certain signature. It doesn't however tell the linker anything about where to find these functions at runtime.
To allow the linker to resolve these calls (decide where to jump to inside your code or in a different shared object), you need to link against the appropriate (pthread) library by adding
-pthread
to your build command line.
[Note that it is also possible to use -lpthread. This previous question expains why -pthread is preferable.]
There are various other issues with the code that will be worthy of attention
The scanf line should be split into printf("Enter number of threads\n");scanf("%d", &num); to get the user prompt displayed
The signature of CreateChain is wrong - it should take a void* argument instead. You can always do something like int num = *(int*)arg; inside the function to retrieve the number of threads.
The logic inside CreateChain looks wrong. You currently compare a pointer against 0 - I presume you mean to compare the number of threads instead? Also, if you don't decrement the number of threads to create somewhere, you'll end up with code that creates threads forever (or until you run out of handles depending on how the different threads get scheduled).
Try compiling like this below :
gcc -Wall -pthread test.c -o test.out
-pthread is an option to tell linker explicitly to resolve the symbols related to <pthread.h>
add -lpthread
gcc -o test test.c -lpthread
I'm trying the code from Tanenbaum's 3e "Modern Operating Systems" and I get compiler errors and warnings:
$ LANG=en_US.UTF-8 cc thread.c
thread.c: In function ‘main’:
thread.c:19:63: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
thread.c:25:1: warning: passing argument 1 of ‘exit’ makes integer from pointer without a cast [enabled by default]
/usr/include/stdlib.h:544:13: note: expected ‘int’ but argument is of type ‘void *’
/tmp/ccqxmMgE.o: In function `main':
thread.c:(.text+0x57): undefined reference to `pthread_create'
collect2: ld returned 1 exit status
This is the code I'm trying
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUMBER_OF_THREADS 10
void *print_hello_world(void *tid)
{
//printf("Hello World. Greetings from thread %d0", tid);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
pthread_t threads[NUMBER_OF_THREADS];
int status, i;
for(i=0; i<NUMBER_OF_THREADS; i++) {
//printf("Main here creating thread %d0", i);
status = pthread_create(&threads[i], NULL, print_hello_world, (void *)i);
if (status != 0) {
//printf("Oops. pthread_create returned error code %d0", status);
exit(-1);
}
}
exit(NULL);
}
Can you help me improve the state of the code so that it will run? There appears to be some errata since the exact code from the book doesn't compile. Thanks
Please link to pthread library, by specifying -lpthread option to your linker.
Also, you should be using pthread_join to wait for all the created threads to complete.
$gcc thread.c -lpthread
This is to link the pthread shared library.
1) You have to link to libpthread to get rid of the linker error:
gcc ..... -lpthread
(note that the -lpthread option must be the last one)!
2) exit(NULL); is wrong; NULL is for pointer types whereas exit wants an int to be supplied; use simply
exit(0);
instead.
The other warnings are just system-dependent pointer and integer size warnings; they can safely be ignored in most cases.
Pl. do not use the exit statement in your main function in this case, since the main may get exited and your threads also will terminate and you may not get the outputs of the print statement in the thread function.
Pl. use pthread_exit instead of exit in main so that even your main thread terminates the other threads can continue.
I have used the following code to create two threads:
//header files
#include <pthread.h>
struct thread_arg
{
int var1;
int var2;
};
void *serv_com(void *pass_arg)
{
struct thread_arg *con = pass_arg;
//required statements irrelevant to the issue
pthread_exit(NULL);
}
void *cli_com(void *pass_arg)
{
struct thread_arg *con = pass_arg;
//required statements irrelevant to the issue
pthread_exit(NULL);
}
int main()
{
pthread_t inter_com;
//necessary code
while(1)
{
th_err_s = pthread_create(&inter_com, NULL, serv_com, (void *)&pass_arg);
th_err_c = pthread_create(&inter_com, NULL, cli_com, (void *)&pass_arg);
if (th_err_s || th_err_c)
{
printf("Alert! Error creating thread! Exiting Now!");
exit(-1);
}
}
pthread_exit(NULL);
return 1;
}
Then I compiled the above code in linux using the following command:
gcc -o sample sample.c
It returned the following error message:
inter.c:(.text+0x374): undefined reference to `pthread_create'
inter.c:(.text+0x398): undefined reference to `pthread_create'
collect2: ld returned 1 exit status
What should I do to correctly compile this file. I am sure it is no syntax error or anything since when I commented off everything inside the while loop, the program was compiling correctly and I verified that the pthread_create syntax is correct. Do I have to issue some other command to compile the file?
EDIT: Is there any problem with the creating of two threads in the above code? The program is just exiting with the error message once it is running. What can be the possible issue and how can I solve it? Thanks in advance.
Try doing this :
gcc -lpthread sample.c
or
gcc -pthread sample.c
above 2 commands will directly create executable a.out
Answer after edit:
1) Wait for the two threads to join main thread using call
int pthread_join(pthread_t thread, void **value_ptr);
2) Create both threads with different ids
3) Also avoid calling pthread_exit from main() if you can, although there is no harm doing that
4) you are calling pthread_create in while(1) this will create infinite threads .. I do not know what are you trying to achieve .
Link to pthread Library when compiling...
gcc -o sample -lpthread sample.c
I am not too sure myself but I would think you could do something like
pthread_t inter_com, inter_com2;
and
th_err_s = pthread_create(&inter_com, NULL, serv_com, (void *)&pass_arg);
th_err_c = pthread_create(&inter_com2, NULL, cli_com, (void *)&pass_arg);
I think it should give you 2 ids of threads. But careful when sharing variables etc between threads. But am glad you resolved it yourself.