I'm trying to install zeromq but I'm having some problems with undefined reference . I used this tutorial to install zeromq in my machine, with the difference that I downloaded version 4.1.4 and not 4.1.2.
Then I'm trying to run the following code (got from zeromq tutorial) in C:
// Hello World server
#include <zmq.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
int main (void)
{
// Socket to talk to clients
void *context = zmq_ctx_new ();
void *responder = zmq_socket (context, ZMQ_REP);
int rc = zmq_bind (responder, "tcp://*:5555");
assert (rc == 0);
while (1) {
char buffer [10];
zmq_recv (responder, buffer, 10, 0);
printf ("Received Hello\n");
sleep (1); // Do some 'work'
zmq_send (responder, "World", 5, 0);
}
return 0;
}
with this line:
gcc program.c -lzmq
and I got this error:
/tmp/cc3OkNsE.o: In function `main':
program.c:(.text+0x18): undefined reference to `zmq_ctx_new'
collect2: error: ld returned 1 exit status
I already did some research but I couldn't find any clear solutions/instructions. Anyone knows how to solve it or what I'm doing wrong?
As pointed by Maarten Artis in the comments above, it wasn't actually linking the library. The correct command line is:
gcc -Wall program.c -o prog -L/usr/local/lib -lzmq
Related
I was having a problem with one application, so i went back to the basics and grabbed the sem_timedwait example from the ubuntu focal online manpages. I modified it slightly to repro the problem.
CASE: sem_post before sem_timedwait
EXPECTED: sem_timedwait to succeed immediately
OBTAINED: sem_timedwait times out
The problem was showing initially on a Docker (WSL disabled) container with Ubuntu 20.04 (g++ 9 multilib)
I then tried from a WSL Debian 9 (g++ 6 multilib) and a WSL Ubuntu 20.04 (g++ 9 multilib) installed fresh from PowerShell
I further installed a full fresh Ubuntu 20.04 VM with g++ 9 multilib on Hyper-V
I also tried apt update && apt upgrade to be sure to be on the latest packages, I also tried at some point to completely remove g++ 9 and all its dependencies and use g++ 10 (which comes with libasan.so.6 instead of libasan.so.5)
Original sem_timedwait example from Ubuntu
Modified version, added a sleep before sem_timedwait so that the call to sem_timedwait happens always after the sem_post. I also added a print of sem_getvalue to verify that the semaphore counter was being incremented correctly to 1.
[File: test_sem.cpp]
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
sem_t sem;
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
static void
handler(int sig)
{
write(STDOUT_FILENO, "sem_post() from handler\n", 24);
if (sem_post(&sem) == -1) {
write(STDERR_FILENO, "sem_post() failed\n", 18);
_exit(EXIT_FAILURE);
}
}
int
main(int argc, char *argv[])
{
struct sigaction sa;
struct timespec ts;
int s;
if (argc != 3) {
fprintf(stderr, "Usage: %s <alarm-secs> <wait-secs>\n",
argv[0]);
exit(EXIT_FAILURE);
}
if (sem_init(&sem, 0, 0) == -1)
handle_error("sem_init");
/* Establish SIGALRM handler; set alarm timer using argv[1] */
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGALRM, &sa, NULL) == -1)
handle_error("sigaction");
alarm(atoi(argv[1]));
/* Calculate relative interval as current time plus
number of seconds given argv[2] */
if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
handle_error("clock_gettime");
ts.tv_sec += atoi(argv[2]);
//this is a cancellation point when the alarm goes off
sleep(atoi(argv[1]) + 2);
int value = 0;
sem_getvalue(&sem, &value);
printf("sem_getvalue(): %d\n", value);
sleep(2);
printf("main() about to call sem_timedwait()\n");
while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR)
continue; /* Restart if interrupted by handler */
/* Check what happened */
if (s == -1) {
if (errno == ETIMEDOUT)
printf("sem_timedwait() timed out\n");
else
perror("sem_timedwait");
} else
printf("sem_timedwait() succeeded\n");
exit((s == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
}
to compile this example i used the following
g++ -std=gnu++17 -m32 -fsanitize=address -fsanitize-recover=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer test_sem.cpp -lstdc++ -lpthread -lasan
to run it, simply ./a.out 2 5
what I obtain is the following unexpected result:
sem_post() from handler
sem_getvalue(): 1
main() about to call sem_timedwait()
sem_timedwait() timed out
the same code compiled WITHOUT the -m32 flag g++ -std=gnu++17 -fsanitize=address -fsanitize-recover=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer test_sem.cpp -lstdc++ -lpthread -lasan gives me the following expected result
sem_post() from handler
sem_getvalue(): 1
main() about to call sem_timedwait()
sem_timedwait() succeeded
the same code compiled WITH the -m32 flag but WITHOUT the libasan g++ -std=gnu++17 -m32 test_sem.cpp -lstdc++ -lpthread -lasan gives me the following expected result:
sem_post() from handler
sem_getvalue(): 1
main() about to call sem_timedwait()
sem_timedwait() succeeded
Just for the sake of me I tried also to replace the signal handler code with a second thread to achieve the same sem_post before sem_timedwait and I obtain the same exact result. I further tried also using the non-POSIX-compliant sem_clockwait using both CLOCK_REALTIME and CLOCK_MONOTONIC and I got the same exact result.
I also tried completely removing g++ 9 and installed g++ 10 (which uses libasan.so.6 instead of libasan.so.5)
Right now I dont know if it is something on my side but seems that Docker Ubuntu 20.04 (no WSL), Debian 9 WSL 2, Ubuntu 20.04 WLS 2, and full Hyper-V Virtual Machine with Ubuntu 20.04 are all giving me the same result.
I tried everything I could think of to no avail.
I am currently writing a shared library that takes a UNIX username and returns a string with all of the groups that user belongs to in [group1, group2, group3...] format.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <utmp.h>
#include <sys/types.h>
#include <grp.h>
#include <pwd.h>
int num_groups = 0;
struct passwd *pwd;
gid_t *groups;
struct group *grp;
FILE *stream;
char *buff;
size_t length;
char *printGroups(char *arg)
{
stream = open_memstream(&buff, &length);
pwd = getpwnam(arg);
getgrouplist(arg, pwd->pw_gid, groups, &num_groups);
groups = malloc(num_groups * sizeof(gid_t));
if (groups == NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
getgrouplist(arg, pwd->pw_gid, groups, &num_groups);
fprintf(stream, " [");
for (int i = 0; i < num_groups; ++i){
grp = getgrgid(groups[i]);
if (i == num_groups - 1)
fprintf(stream, "%s", grp->gr_name);
else
fprintf(stream, "%s ", grp->gr_name);
}
free(groups);
fprintf(stream, "]");
fclose(stream);
return buff;
}
This is main function in my shared library that returns the string. I verified that the function is indeed correct - the same logic works in a standalone program using printf instead of open_memstream stringstream.
The library however segfaults and I can't pinpoint why. Valgrind does not output anything useful:
gcc -shared -fpic -g -Wall lib.c
valgrind ./a.out
==9916== Process terminating with default action of signal 11 (SIGSEGV)
==9916== Access not within mapped region at address 0x0
==9916== at 0x1: ???
==9916== by 0xFFF000672: ???
Same goes for gdb backtrace:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000001 in ?? () (gdb) backtrace
#0 0x0000000000000001 in ?? ()
#1 0x00007fffffffe6e9 in ?? ()
#2 0x0000000000000000 in ?? ()
I am out of ideas. Could somebody point me to a solution, ethier an error in the .so source or the reason why both Valgrind and gdb print ??? despite using the -g flag when compiling?
It looks like you're attempting to run the shared library directly. That's not how shared libraries work. They're referenced by other programs that use them.
For example, this code would use your library:
#include <stdio.h>
#include <stdlib.h>
char *printGroups(char *);
int main()
{
char *groups = printGroups("root");
printf("groups: %s\n", groups);
free(groups);
return 0;
}
If you first compile your library like this:
gcc -shared -fpic -g -Wall lib.c -o libmylib.so
Then, assuming this library lives in the same directory as the the above test code, you compile the test code like this:
gcc -g -Wall -Wextra -L. -o mytest mytest.c -lmylib
Then set an environment variable to find your library:
export LD_LIBRARY_PATH=.
You can then run the test program which will use your library.
I am using the standard __wrap_function and __real_function to intercept function calls with -Wl,--wrap=function. This works successfully for most functions like malloc, fopen, etc. However, I am unable to wrap these two functions:
int connect(int, const struct sockaddr*, socklen_t)
int stat(const char*, struct stat*)
With these functions, the linker complains with undefined reference to __real_connect and __real_stat.
Is there any particular reason for this? (Note: I can also wrap socket functions for example)
It is likely you forgot to add -Wl,--wrap=connect and -Wl,--wrap=stat to your link line.
This works for me:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
int __wrap_connect (int s, const struct sockaddr *addr, socklen_t len)
{
puts(__func__);
return __real_connect(s, addr, len);
}
int __wrap_stat (const char *path, struct stat *buf)
{
puts(__func__);
return __real_stat(path, buf);
}
int main(void) {
connect(0, NULL, 0);
stat("/", 0);
return 0;
}
When compiled on my system.
$ uname -s -r
Linux 2.6.32-696.16.1.el6.x86_64
$ gcc --version | grep gcc
gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18)
$ gcc c.c -Wl,--wrap=connect -Wl,--wrap=stat
$
However, when leaving off -Wl,--wrap=stat, for example, I get:
$ gcc c.c -Wl,--wrap=connect
/tmp/cchVzvsE.o: In function `__wrap_stat':
c.c:(.text+0x65): undefined reference to `__real_stat'
collect2: ld returned 1 exit status
$
It seems like the error was caused due to cmake issues. Clearing the cmake cache and running cmake . followed by make all resolved it.
I'm trying to use libusb for a project but i'm unable to get the library working properly. Here is some source code i'm trying to compile. It doesn't do anything special. It's just a dummy program that gets the USB driver list then frees it.
#include <stdio.h>
#include <usb.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
struct libusb_device **devs;
struct libusb_context *context = NULL;
size_t list;
size_t i;
int ret;
ret = libusb_init(&context);
if(ret < 0)
{
perror("libusb_init");
exit(1);
}
list = libusb_get_device_list(context, &devs);
if(list < 0)
{
fprintf(stderr, "error in getting device list\n");
libusb_free_device_list(devs, 1);
libusb_exit(context);
exit(1);
}
libusb_free_device_list(devs, 1);
libusb_exit(context);
return 0;
}
I compile with
gcc -o test test.c -lusb
I get the error
/tmp/cc2hwzii.o: in function 'main:
test.c:(.text+0x24): undefined reference to 'libusb_init'
test.c:(.text+0x59): undefined reference to 'libusb_get_device_list'
test.c:(.text+0x8e): undefined reference to 'libusb_free_device_list'
test.c:(.text+0x9f): undefined reference to 'libusb_exit'
collect2: error: ld returned 1 exit status
I'm running ubuntu 14.04.3
I've installed libusb by sudo apt-get install libusb-dev
I've searched for my header file and it is called usb.h
I've looked to make sure I have the correct flag and it's -lusb
any ideas? I'd appreciate the help. If any more information is needed just ask.
those libusb_init are included in libusb-1.0.
you have to install libusb-1.0-0-dev
$ sudo apt-get install libusb-1.0-0-dev
$ gcc -o test test.c -lusb-1.0
/usr/lib/x86_64-linux-gnu/pkgconfig/libusb.pc which is included in libusb-dev says that the version is 0.1.12
and
/usr/lib/x86_64-linux-gnu/pkgconfig/libusb-1.0.pc which is included in libusb-1.0-0-dev says that the version is 1.0.17.
http://www.libusb.org/ says that 0.1 is legacy, and seems that API is different from 1.0.
You forgot to include the file that defines the functions, such as libusb_init. Have you tried including libusb.h?
I am writing a multi-process program using named semaphores, in the master process I am opening the semaphore with the following code
semaphore = sem_open("/msema",O_RDWR|O_CREAT|O_TRUNC,00777,1);
if (semaphore == SEM_FAILED)
perror("SEMAPHORE");
and in the child program
count_sem=sem_open("/msema",O_RDWR);
if(count_sem==SEM_FAILED)
{
perror("sem_open");
return 1;
}
on sem_wait()
do {
errno=0;
printf("BeforeSemWait\n");
rtn=sem_wait(count_sem);
printf("afterSemWait\n");
} while(errno==EINTR);
if(rtn < 0) {
printf("Error\n");
perror("sem_wait()");
sem_close(count_sem);
return 1;
}
I am getting a bus error from sem_wait()
BeforeSemWait
Program received signal SIGBUS, Bus error.
0x00a206c9 in sem_wait##GLIBC_2.1 () from /lib/libpthread.so.0`
What am I doing wrong?
edit: entire code:
master.c: http://pastebin.com/3MnMjUUM
worker.c http://pastebin.com/rW5qYFqg
You must have somewhere else a bug in your program. The following works here (O_TRUNC is not needed):
semproducer.c:
#include <fcntl.h>
#include <stdio.h>
#include <semaphore.h>
int main () {
sem_t *sem=sem_open("/msema",O_RDWR|O_CREAT /* |O_TRUNC*/ ,00777,1);
if (sem==SEM_FAILED) {
perror("sem_open");
}
else {
while (1) {
sem_post (sem);
printf ("sem_post done\n");
sleep (5);
}
}
}
semconsumer.c:
#include <fcntl.h>
#include <stdio.h>
#include <semaphore.h>
#include <errno.h>
int main () {
sem_t *count_sem=sem_open("/msema",O_RDWR);
if(count_sem==SEM_FAILED) {
perror("sem_open");
return 1;
}
do {
int rtn;
do {
errno=0;
rtn=sem_wait(count_sem);
} while(errno==EINTR);
if(rtn < 0) {
perror("sem_wait()");
sem_close(count_sem);
return 1;
}
printf ("sema signalled\n");
} while (1);
}
compile with gcc semproducer.c -o semproducer -lrt and gcc semconsumer.c -o semconsumer -lrt
I encountered this exact error.
It was because I hadn't linked in the Real-Time library that provides POSIX real-time functionality. The commenter above briefly mentioned the "-lrt" parameter in his solution, but did not emphasize it as the reason that you were getting your exception. You can verify this with the following code:
int main(void)
{
sem_t* my_sem = sem_open("/test_sem", O_CREAT, S_IRUSR | S_IWUSR, 0);
sem_wait(my_sem);
}
Assuming this is in the file "test.c" and I run the following:
gcc ./test.c -o test.out
./test.out
I get the Bus Error Output:
Bus error
But with the following command:
gcc ./test.c -o test.out -lrt
./test.out
The program does not except, and instead waits on the semaphore forever which is expected with a value of zero.
You should NOT pass -lrt, however. The linux documentation for sem_wait(3) indicates that the correct command is "-pthread". Substituting "-lrt" with "-pthread" in my testing indicates that it has the same effect, so the list of flags passed by -pthread on Linux likely includes "-lrt".
As such, the correct compiler invocation would be
gcc ./test.c -o test.out -pthread