g++ linking libs instead of *.o containing static members leads to segfault - static

I observed segfaults if I used linking libraries instead of linking all the primary compiler output with g++. This problem occurs with libraries with classes with static members. And I don't find a solution with libs. What went wrong?
Simplified: I created two libraries called alpha and beta. Alpha contains a static member (race conditions were excluded). The library alpha depends on beta. And alpha and beta depend on a third library, the public library gamma (in my case Cairo).
The static member is defined as private within a class Alpha and access via getters and setters with mutex locks.
I compile my the source code for alpha
g++ -fPIC -DPIC `pkg-config --cflags gamma` alpha*.cpp -c
ar rcs alpha.a alpha*.o
and beta, respectively
g++ -fPIC -DPIC `pkg-config --cflags gamma` beta*.cpp -c
ar rcs beta.a beta*.o
Now, I want to use these libs (alpha, beta, and gamma) in my program delta. I tried two different ways to compile and link in two steps. First, compile and simply link the compiled objects:
g++ -fPIC -DPIC `pkg-config --cflags gamma` delta.cpp -c -o delta.o
g++ -fPIC -DPIC alpha*.o beta*.o delta.o `pkg-config --libs gamma` -o delta
This compiles, links and runs. Without any problems.
But if I want to use the .a libs instead and try:
g++ -fPIC -DPIC `pkg-config --cflags gamma` delta.cpp -c -o delta.o
g++ -fPIC -DPIC -lalpha -lbeta delta.o `pkg-config --libs gamma` -o delta
This compiles and links. But produces a segfault on running. During the very first access to the static member.

g++ -fPIC -DPIC -lalpha -lbeta delta.o pkg-config --libs gamma -o delta
Note that this command line is generally incorrect. See this post. You should use this command instead:
g++ delta.o -lalpha -lbeta `pkg-config --libs gamma` -o delta
This may or may not solve your crash.
In general, you are probably depending on the order of initialization of globals, which is somewhat hard to control. The best advice is to not do that.
What do I mean by order of initialization? Consider these two files:
// a.cc
const int foo = 42;
// b.cc
extern int foo;
const int bar = foo;
Question: what is the value of bar?
Answer: you can't generally tell. It could be 0, 42, and I believe could also be some other random value.

Related

SDL 2 C Compiler Flags

Whenever I run the following, I get undefined references to all the SDL-related functions used in my program:
cc -lSDL2 -lGL *.o
I believe this is caused by the lack of -l linker flags.
GCC arguments are positional, put the link flags after your o files:
gcc *.o -lSDL2 -lGL
Also, if you're on a proper full Linux system I'd recommend using pkg-config to pull compiler/linker flags:
gcc -c main.c `pkg-config sdl2 --cflags`
gcc main.o `pkg-config sdl2 --libs`

How to find the library <openssl/des.c> and usit in C programs [duplicate]

I have built OpenSSL from source (an intentionally old version; built with ./config && make && make test) and would prefer to use what I have built without doing make install to link against my program.
The command that's failing is:
gcc -Wall -Wextra -Werror -static -Lopenssl/openssl-0.9.8k/ -lssl -lcrypto
-Iopenssl/openssl-0.9.8k/include -o myApp source1.o source2.o common.o`
And I receive a series of errors similar to:
common.c:(.text+0x1ea): undefined reference to `SSL_write'
This makes me think there's something funky with my OpenSSL. If I omit -Lopenssl/openssl-0.9.8k/ from my command, the error changes to being unable to:
/usr/bin/ld: cannot find -lssl
/usr/bin/ld: cannot find -lcrypto
Am I compiling OpenSSL incorrectly? Or how should I best resolve this?
Silly "Linux-isms" strike again! Apparently, I need to change my command such that the -L and -l stuff is at the end like (despite what man gcc seems to indicate):
gcc -Wall -Wextra -Werror -static -o myApp source1.o source2.o common.o -Lopenssl/openssl-0.9.8k/ -lssl -lcrypto -Iopenssl/openssl-0.9.8k/include
Why don't you want to use make install? It can copy generated binaries in the directory you want if you previously passed it to ./configure --prefix $HOME/target_library_install_directory
If you used this trick with every library you build and install, you could then add the target directory to the LIBRARY_PATH environment variable and avoid using -L option.
If you use Autotools, or you are building an Autools project like cURL, then you should be able to use pkg-config. The idea is the Autotools package will read OpenSSL's package configuration and things will "just work" for you.
The OpenSSL package configuration library name is openssl.
You would use it like so in a makefile based project.
%.o: %.c
$(CC) -o $# -c `pkg-config --cflags openssl` $^
target: foo.o bar.o baz.o
$(CC) -o $# `pkg-config --libs openssl` $^
Also see How to use pkg-config in Make and How to use pkg-config to link a library statically.
Another approach is to use pkg-config to preserve compatibility. This is an example of makefile when needs to link OpenSSL.
CC = gcc
CFLAGS = \
-I. \
-D_GNU_SOURCE=1
LDFLAGS = `pkg-config --libs inih`
LDFLAGS += `pkg-config --libs libcurl`
LDFLAGS += `pkg-config --libs liburiparser`
LDFLAGS += `pkg-config --libs openssl`
# Executable
foo: foo.o
$(CC) -o $# $^ $(LDFLAGS)
foo.o: foo.c
$(CC) -c $(CFLAGS) $< -o $#

scons linking problems depending on CC

I'm compiling a library that comes with a scons script. According to the documentation scons does everything automatically and stuff should just work.
However, the build succeeds or fails, depending on what I set CC to (even though I always invoke the same compiler):
/usr/bin/ld: context.os: relocation R_X86_64_32S against `a local symbol' can not be used when making a shared object; recompile with -fPIC
context.os was built with the following arguments.
env cc -o context.os -c ... -Wall -O2 -DNDEBUG -I. -I/usr/local/include ... context.c
So scons forgets the -fPIC argument. However if I set CC=cc it succeeds:
cc -o context.os -c ... -Wall -O2 -fPIC -DNDEBUG ...
The same if I set CC="ccache cc":
ccache cc -o context.os -c ... -Wall -O2 -fPIC -DNDEBUG ...
And of course, with -fPIC set, linking succeeds in both cases.
So, I wonder how does scons position independent code trigger work and why does it screw up in the CC="env cc" case?

How to compile with a .o file that was compiled with other .o files (C99)

consider c.c a code that includes a.h and b.h, and main.c a code that includes c.h
i tried to compile it like so
gcc --std=c99 -o a.o -c a.c
gcc --std=c99 -o b.o -c b.c
gcc --std=c99 -o c.o -c c.c a.o b.o
but when I run the last one, gcc yells at me
gcc --std=c99 -o c.o -c c.c a.o b.o
gcc: warning: a.o: linker input file unused because linking not done
gcc: warning: b.o: linker input file unused because linking not done
and then when I try to compile the main.c file using gcc -o main main.c c.o it says that there are a lot of undefined references, which is predictable once the c file was not correctly compiled.
I've seen some similar questions here at stackoverflow, but I couldn't get it to work neither way.
I'm on Arch Linux running gcc v4.9.2-3
First, it is -std=c99 with a single dash.
I guess you are on Linux.
Then, you always should pass -Wall -Wextra -g (especially since you are a newbie) to gcc : -Wall ask for nearly all warnings, -Wextra for even more warnings, -g ask for debug information.
At last, you want to produce an executable myprog (don't name executables as c.o, this is supposed to be an object file) with
gcc -std=c99 -Wall -Wextra -g -o myprog c.c a.o b.o
You need to remove any -c since you want the linking to happen.
If you really mean -but that is very unusual today, better make shared libraries!- to agglomerate several object files into one all.o (to be linked later with other objects) you might try the -r linker option
gcc -std=c99 -Wall -Wextra -g -r c.c a.o b.o -o all.o
But last time I tried it was in the previous century, so details could be wrong.
There are very few reasons to agglomerate objects using the -r linker option. Unless you really know what you are doing, you are very probably wrong (in trying -r).
Perhaps you want to make a software library. These days it is much better to make a shared library. A shared library (technically an ELF shared object) should contain position independent code. So, assuming you have three translation units t1.c, t2.c, t3.c you first compile them as PIC :
gcc -std=c99 -Wall -Wextra -g -fPIC t1.c -c -o t1.pic.o
gcc -std=c99 -Wall -Wextra -g -fPIC t2.c -c -o t2.pic.o
gcc -std=c99 -Wall -Wextra -g -fPIC t3.c -c -o t3.pic.o
then you link all these PIC object files into a shared library libmyt.so
gcc -std=c99 -Wall -Wextra -g -shared \
t1.pic.o t2.pic.o t3.pic.o \
-o libmyt.so
Later you'll use this shared library e.g. as
gcc -std=c99 -Wall -Wextra -g main.o -o myprog -Wl,-rpath . libmyt.so
or as
gcc -std=c99 -Wall -Wextra -g main.o -o myprog -Wl,-rpath . -L. -lmyt
You might consider static linking with ar to make a static library libmyt.a but I don't recommend that.
Of course, you'll debug your program using gdb ./myprog and you could try running it with ./myprog. To use valgrind, try valgrind ./myprog
If you have several translation units, better learn how to use GNU make. Read the Program Library HowTo and this and these hints.

linking pthread library issue

Am facing a problem that may be slightly complicated to explain and understand as giving the entire picture would be too big and difficult.
Please excuse me for it.
Consider the following Makefile:
all: clients.so simulator backup
LD_PRELOAD=/home/Juggler/client/clients.so ./simulator
backup: backup.c libclient.a
gcc backup.c -o backup -L /home/Juggler/client -L. -lclient -ldl
simulator: simulator.c libclient.a
gcc -g simulator.c -o simulator -L /home/Juggler/client -L. -lclient -ldl -pthread
libclient.a: libclient.o client.o
ar rcs libclient.a libclient.o client.o
libclient.o:libclient.c
gcc -c libclient.c -o libclient.o -pthread
clients.so: client.o client_invoke.o
ld -shared -o clients.so client_invoke.o client.o -ldl
client_invoke.o: client_invoke.c
gcc -Wall -fPIC -DPIC -c -g client_invoke.c
client.o: client.c
gcc -Wall -fPIC -DPIC -c -g client.c -ldl -pthread
We call function written in client.c from libclient.c and these functions in client.c make call to pthread_key_create(), pthread_setspecific..etc.
Threads are created by simulator.c and theses threads access functions written in he other files.
On doing make...Errors like the following appear.
/home/Juggler/client/libclient.a(client.o):In function 'setup_connection':
/home/Juggler/client/client.c:35: undefined reference to 'pthread_setspecific'
pthread.h has been included in both client.c and libclient.c
Would be grateful for anypointers . I understand information is very less...
Thanks
On linux, pthread functions live in the libpthread library. So you have to link to that.
The proper way, when using pthreads, is to compile and link using the -pthread , which, among other things, will link in the pthread library. You have the -pthread flag for some of your executables, but not for others, and not for your clients.so library, so add the flag where required.
Also, remember, when you are creating a shared library, you should compile the source files with the -fPIC flag.
(And, seems you are calling ld directly to produce the client.so library, you really should use gcc to do the linking.)

Resources