Cant find Shared Object on runtime. KRPC - c++

Im trying to use a library named krpc. It is installed with cmake according to the instructions. https://krpc.github.io/krpc/cpp/client.html#using-the-library
This is the test program:
#include <iostream>
#include <krpc.hpp>
#include <krpc/services/krpc.hpp>
int main() {
krpc::Client conn = krpc::connect();
krpc::services::KRPC krpc(&conn);
std::cout << "Connected to kRPC server version " << krpc.get_status().version() << std::endl;
}
Compiled with:
g++ main.cpp -std=c++11 -lkrpc -lprotobuf
ldd returns: (other libraries is found)
ldd a.out
libkrpc-0.3.7.so => not found
The library is installed from ./krpc-cpp-0.3.7
which contains libkrpc.so.0.3.7.
How do I properly install the library? I tried changing the name of the .so. And making softlinks to /ust/lib. And running ldconfig anew afterwards.

Had to copy the .so to /usr/lib, then run ldconfig.
-Thanks to #Xin Huang

Related

using std::thread in shared library causes SIGSEGV

I just came to Linux c++ programming from Windows. Trying to make a shared library libso.so, which uses std::thread. The shared library will be loaded by other people and call the export function. The test code:
// so.cpp, the .so library
#include <iostream>
#include <thread>
using namespace std;
extern "C"
void run() {
cout << "run() begin" << endl;
std::thread t([] {
});
t.join();
cout << "run() end" << endl;
}
// test.cpp, the test loader
#include <dlfcn.h>
int main() {
typedef void (*run_t)();
auto dll = dlopen("libso.so", RTLD_LAZY);
run_t run = (run_t) dlsym(dll, "run");
run();
}
// The CMakeLists.txt file
cmake_minimum_required(VERSION 3.0)
PROJECT (test)
Include_Directories(${PROJECT_SOURCE_DIR})
Link_Directories(${PROJECT_BINARY_DIR})
add_library(so SHARED so.cpp )
target_link_libraries(so pthread)
add_executable( test test.cpp )
target_link_libraries(test pthread dl)
It crashes in the run() function, the output is:
run() begin
“./test” terminated by signal SIGSEGV (Address boundary error)
The std::thread seems work fine in executable, but not in shared library. What do I miss?
The environment: g++ 9.3.0, cmake 3.16.3
Edited:
Try ldd.
ldd ./test shows no pthread, but ldd ./libso.so has libpthread.so.0.
The difference of linking param with SET(CMAKE_VERBOSE_MAKEFILE TRUE)
// linking executable 'test'
/usr/bin/c++ -rdynamic CMakeFiles/test.dir/test.cpp.o -o test -L/e/c/1/kali -Wl,-rpath,/e/c/1/kali -ldl -lpthread
// linking library 'libso.so'
/usr/bin/c++ -fPIC -shared -Wl,-soname,libso.so -o libso.so CMakeFiles/so.dir/so.cpp.o -L/e/c/2/kali -Wl,-rpath,/e/c/1/kali -lpthread
The only difference is -fPIC, I googled and add set_property(TARGET test PROPERTY POSITION_INDEPENDENT_CODE ON) to the executable, but nothing changed.
Workaround 1
Since the .so has libpthread.so.0, I tried to add the code in .so to the executable:
int main() {
std::thread t([]{}); // to make executable linking to `pthread`
t.join();
// ... load dll and call run function
}
And it works, now the ldd ./test shows libpthread.so.0 and no crash. Which means: if a shared library uses std::thread and an executable wants to load it, the executable itself must also use std::thread.
Workaround 2:
The std::thread works fine in executable, but crashes in shared library. Found some related discuss, the walkaround is using boost::thread instead of std::thread and linking to boost_thread library, no crash .
I guess the problem is more related to dynamic linking
than threads.
The call dlopen("libso.so", RTLD_LAZY) will try to
find the library in a standard location.
Except if you set the LD_LIBRARY_PATH environment
variable to something that includes . (the current
directory) this library won't be found.
For a simple test you can either:
use export LD_LIBRARY_PATH=. in the terminal before
launching your program,
use dlopen("./libso.so", RTLD_LAZY) in your source code.
After using dlopen() or dlsym() if you obtain a null
pointer, then dlerror() can help displaying the reason
of the failure.
Note that on Windows the current directory and the executable
path are standard search paths for dynamic libraries; on UNIX
this is not the case, which could be surprising when changing
the target platform.
edit
cmake uses the -Wl,-rpath option to hardcode a library search
path in the executable, so all of what I explained above becomes
useless for this problem.
Assuming the dynamic library is found, the only way I can reproduce
the crash is to forget pthread in target_link_libraries for
test.
second edit
I finally managed to reproduce the crash with Ubuntu (in WSL).
Apparently your linker decides to ignore the libraries that are
not directly used by the executable.
This behavior suggests that the linker option --as-needed is
switched on by default.
To contradict this default behaviour, you need to pass the linker
option --no-as-needed before -lpthread.
This way, you don't have to insert a dummy thread in your
executable.
Using set(CMAKE_CXX_FLAGS -Wl,--no-as-needed) in the CMakeLists.txt
file you provide did the trick for me.

Am not able to link a shared library and run executable on mac (Intel tbb)

I was trying to compile and link Intel's tbb into a simple program on my mac, but I keep getting an error saying that the library was linked properly.
dyld: Library not loaded: #rpath/libtbb.dylib
Referenced from:<path>/./a.out
Reason: image not found
Trace/BPT trap: 5
The test program I used has the following code
#include <iostream>
#include <cassert>
#include <tbb/concurrent_queue.h>
int main() {
auto q = tbb::concurrent_queue<int>{};
q.push(1);
auto top_value = int{};
assert(q.try_pop(top_value));
assert(top_value == 1);
assert(q.empty());
return 0;
}
And this is how I built the library (with downloading the library included for your convenience)
curl -OL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb2017_20170118oss_src.tgz
tar -xzvf tbb2017_20170118oss_src.tgz
mv tbb2017_20170118oss tbb
rm tbb2017_20170118oss_src.tgz
cd tbb
make tbb
mv build/*_release build/tbb_release
And I tried to compile the program with this command
g+++ another.cpp -I tbb/include -L tbb/build/tbb_release -ltbb -ldl
And then on running the program I get the error above. Any ideas on how I can go about fixing this?
My compiler's version is clang-800.0.42.1 and the operating system I am running is 10.11.5
Thanks!

c++ program using GMP library

I have installed GMP using the instruction on this website: http://www.cs.nyu.edu/exact/core/gmp/
Then I looked for an example program using the library:
#include <iostream>
#include <gmpxx.h>
using namespace std;
int main (void) {
mpz_class a, b, c;
a = 1234;
b = "-5678";
c = a+b;
cout << "sum is " << c << "\n";
cout << "absolute value is " << abs(c) << "\n";
cin >> a;
return 0;
}
But if I compile this using the command: g++ test.cpp -o test.exe, it says gmpxx.h: no such file or directory.
How can I fix this? I am kind of new to this. And I am using MinGW.
Get the actual version here GNU GMP Library. Make sure you configure it to be installed in /usr/lib (pass --prefix=/usr to configure).
Here you have documentation: GNU GMP Manual.
You are not using the lib correctly. I don't know if you can directly access mpx values
with C++ functions but, here you have a working example of what you wanted to achieve:
#include<iostream>
#include<gmp.h>
using namespace std;
int main (int argc, char **argv) {
mpz_t a,b,c;
mpz_inits(a,b,c,NULL);
mpz_set_str(a, "1234", 10);
mpz_set_str(b,"-5678", 10); //Decimal base
mpz_add(c,a,b);
cout<<"\nThe exact result is:";
mpz_out_str(stdout, 10, c); //Stream, numerical base, var
cout<<endl;
mpz_abs(c, c);
cout<<"The absolute value result is:";
mpz_out_str(stdout, 10, c);
cout<<endl;
cin.get();
return 0;
}
Compile with:
g++ -lgmp file.cpp -o file
Here is the correct procedure for setting up the current (as of 7/2/13) GNU bignum libraries with Eclipse CDT, MinGW, and msys for C++. To get through this, you should have used Unix or Linux before, as well as Windows, and you should have a vague recollection of programming and compiling programs. This is the culmination of over a week of research and hardcore frustration, so if I messed something up note it politely or I will blow you up with the power of my mind!
I assume you have already downloaded and installed Eclipse and MinGW and have installed msys into MinGW. You must install MinGW before msys!
Download the tarball for the GMP libraries from gmplib.org to ${gmp_download}. I downloaded the gmp-5.1.2.tar.xz because I have never used lzip and didn't know if it was available in msys.
Open up an msys window (essentially a bash shell). cd ${gmp_buid} and tar -Jxvf ${gmp_download}/gmp-x.x.x.tar.xz
Those tar options are different from what you may find elsewhere on the web! -Jxvf is right for xz (and I think lzip), but for gzip you use -xzvf.
cd gmp-x.x.x and run ./config.guess. Write down the output. You will need it next.
Run ./configure --prefix=${gmp_build} --build= --enable-cxx --with-gnu-ld
Apparently if you don't explicitly tell GMP to build for your platform it builds everything, which is bad. The cxx option builds the C++ libraries and --with-gnu-ld allows it to work with ld. Pretty straightforward.
make
make install
EX: suppose you installed to C:/gmp. You should have gmp/include/gmp.h and gmpxx.h. You should also have gmp/lib/libgmp.a, libgmp.la, libgmpxx.a, libgmpxx.la. You should also have a share directory with stuff in it.
Set up eclipse:
Go to project --> properties
Under C/C++ build --> Environment edit the PATH variable and add ${gmp_build}/include;${gmp_build}/lib
Under C/C++ build --> settings --> tool settings --> GCC Assembler --> general add ${gmp_build}/include as an include path.
Same place but --> GCC C++ compiler --> Includes add ${gmp_build}/include as an include path.
Same place --> GCC C++ compiler --> Miscellaneous add -lgmp -lgmpxx to the END of the line. THE END OF THE LINE!
Same place --> GCC C compiler Add the same include paths and miscellaneous options as before.
Same place --> MinGW C++ linker --> Libraries Add to the "Libraries (-l)" both gmp and gmpxx IN THAT ORDER! Now add ${gmp_build}/lib to "LIbrary Search Path (-L)"
Under C/C++ General --> Paths & Symbols --> Incudes Tab check that you have ${gmp_build}/include in your include directories for Assembly, C, and C++. If they aren't there you may have messed up an earlier step. They should be auto populated by Eclipse.
Same place --> Libraries Tab check that you have gmp and gmpxx IN THAT ORDER. It should already be populated.
Same Place --> Library Paths Tab Check for ${gmp_build}/lib which should already be there.
Hit "Apply" and make sure you rebuild the index or the changes won't take. Hit OK to close out.
Run this short program to verify your setup:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <gmp.h>
#include <gmpxx.h>
using namespace std;
int main ()
{
mpz_t p;
mpz_init_set_ui (p,3);
return 0;
}
Your compile commands should look similar to this:
g++ "-IC:\gmp\include" -O0 -g3 -Wall -c -fmessage-length=0 -lgmp -lgmpxx -o main.o "..\main.cpp" g++ "-LC:\gmp\lib" -o GMPDebug.exe main.o -lgmp -lgmpxx
Notes:
The order of the options is important. I don't know all of the whys, but if the second command line (which links the program) has the -lgmp -lgmpxx flags before the -o option, the linking will fail miserably.
The -l flag is a tricky one. It actually says "Go look in -L for liblibrary.a". In this case "Go look in C:\gmp\lib for libgmp.a and libgmpxx.a".
I have heard of bugs involving cout and the 64 bit version of eclipse, so I am using the 32 bit version, where I am seeing the same bug. :-)
Since there are very small examples in gmp library docs, I'm including exponentiation example for reference:
Program calculates 2 ^ 20000
#include <iostream>
#include <gmp.h>
using namespace std;
int main(void) {
mpz_t result, base;
mpz_inits(result,base,NULL);
mpz_set_str(base, "2", 10);
mpz_pow_ui(result, base, 20000);
mpz_out_str(stdout, 10, result);
return 0;
}
Compile:g++ -o gmp_pow_test gmp_pow_test.cpp -lgmp
Run :./gmp_pow_test
Install gmp library on Ubuntu with following: sudo apt-get install libgmp-dev libgmpxx4ldbl
You need to tell the compiler what libraries you want to use.
g++ -lgmp -lgmpxx file.cpp -o file
It is probably too late to be useful, but...
First, your program works just fine. As others pointed out, you need to (a) ensure that GMP library is installed (including its gmpxx extension, and all the relevant files), and (b) that you're telling the compiler where to find both the include files, and the libraries to link with.
In my case include files are in /opt/local/include, and the libraries are in /opt/local/lib (where Macports placed them :).
Here's the code:
#include <iostream>
#include <gmpxx.h>
using namespace std;
int main (void) {
mpz_class a, b, c;
a = 1234;
b = "-5678";
c = a+b;
cout << "sum of " << a << " and " << b << " is " << c << "\n";
cout << "absolute value is " << abs(c) << "\n";
// cin >> a;
return 0;
}
Here's the compile/link command:
clang++ -o gmpxx-tst -I/opt/local/include gmpxx-tst.cpp -L/opt/local/lib -lgmpxx -lgmp
Here's what invocation of gmpxx-tst produces:
$ ./gmpxx-tst
sum of 1234 and -5678 is -4444
absolute value is 4444
$
You'll need to tell the compiler where the header file is.
g++ test.cpp -I/path/to/directory/that/contains/the/header -o test.exe
I have tried so many solutions and all of them has some problems
Here is the best way to install GMP and eclipse
Follow this link
http://www.multigesture.net/articles/how-to-install-mingw-msys-and-eclipse-on-windows/
You need to make sure of the following that hasn't been mentioned there:
When installing MinGW choose a path that contains no space like "c:\MinGW"
Once installed, From start open MinGW installation manger
choose all the basics
-then under MinGW, choose all GMP libraries to be installed
Apply changes
After that you will install JDK, then Add "C:\Program Files\Java\jdk1.8.0_121\bin" to PATH system variable
After installing Eclipse go to:
GCC C++ compiler --> Miscellaneous add -lgmp -lgmpxx to the END of the line
MinGW C++ linker --> Libraries Add to the "Libraries (-l)" both gmp and gmpxx IN THAT ORDER
gooooo ahead.

openCV program compile error "libopencv_core.so.2.4: cannot open shared object file: No such file or directory" in ubuntu 12.04

I compiled and installed openCV 2.4.2 in ubuntu 12.04. Under /usr/local/include I can see the directories /usr/local/opencv and /usr/local/opencv2.
Here is the code I wrote:
#include <cv.h>
#include <highgui.h>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc,char **argv)
{
Mat image;
image = imread(argv[1],1);
if(argc != 2 || !image.data)
{
cout << "No image data\n";
return -1;
}
namedWindow("Display Image",CV_WINDOW_AUTOSIZE);
imshow("Display Image",image);
waitKey(0);
return 0;
}
I compiled it using this command line:
g++ DisplayImage.cpp -o DisplayImage `pkg-config opencv --cflags --libs`
There were no compile time errors, however when I try to run the resulting binary with /DisplayImage code.png I get the following error message:
./DisplayImage: error while loading shared libraries: libopencv_core.so.2.4: cannot open shared object file: No such file or directory
You haven't put the shared library in a location where the loader can find it. look inside the /usr/local/opencv and /usr/local/opencv2 folders and see if either of them contains any shared libraries (files beginning in lib and usually ending in .so). when you find them, create a file called /etc/ld.so.conf.d/opencv.conf and write to it the paths to the folders where the libraries are stored, one per line.
for example, if the libraries were stored under /usr/local/opencv/libopencv_core.so.2.4 then I would write this to my opencv.conf file:
/usr/local/opencv/
Then run
sudo ldconfig -v
If you can't find the libraries, try running
sudo updatedb && locate libopencv_core.so.2.4
in a shell. You don't need to run updatedb if you've rebooted since compiling OpenCV.
References:
About shared libraries on Linux: http://www.eyrie.org/~eagle/notes/rpath.html
About adding the OpenCV shared libraries: http://opencv.willowgarage.com/wiki/InstallGuide_Linux
To make it more clear(and to put it together) I had to do Two things mentioned above.
1- Create a file /etc/ld.so.conf.d/opencv.conf and write to it the paths of folder where your opencv libraries are stored.(Answer by Cookyt)
2- Include the path of your opencv's .so files in LD_LIBRARY_PATH ()
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/opencv/lib
Find the folder containing the shared library libopencv_core.so.2.4 using the following command line.
sudo find / -name "libopencv_core.so.2.4*"
Then I got the result:
/usr/local/lib/libopencv_core.so.2.4.
Create a file called
/etc/ld.so.conf.d/opencv.conf
and write to it the path to the folder where the binary is stored.For example, I wrote /usr/local/lib/ to my opencv.conf file.
Run the command line as follows.
sudo ldconfig -v
Try to run the command again.
Umair R's answer is mostly the right move to solve the problem, as this error used to be caused by the missing links between opencv libs and the programme. so there is the need to specify the ld_libraty_path configuration.
ps. the usual library path is suppose to be:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
I have tried this and it worked well.
Add this link:
/usr/local/lib/*.so.*
The total is:
g++ -o main.out main.cpp -I /usr/local/include -I /usr/local/include/opencv -I /usr/local/include/opencv2 -L /usr/local/lib /usr/local/lib/*.so /usr/local/lib/*.so.*

xerces-c 2.8 : error while loading shared libraries

I'm trying to compile a program running on an HP UX server on a Red Hat Linux.
It uses xerces-c library to parse xml files. Compilation is ok, but when i try to run it, I get the following message
./a.out: error while loading shared
libraries: libxerces-c.so.28: cannot
open shared object file: No such file
or directory
I wrote a very simple program to try and understand whats going on:
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/TransService.hpp>
#include <xercesc/parsers/SAXParser.hpp>
#include <xercesc/util/OutOfMemoryException.hpp>
int main(int argc, char* argv[])
{
return 0;
}
And compiled it like this:
g++ test.cpp
-L./xml/xerces-c_2_8_0/lib -lxerces-c -I./xml/xerces-c_2_8_0/include
Surprisingly the file is actually there:
lib]$ ls
libxerces-c.a libxerces-c.so.28 libxerces-depdom.a libxerces-depdom.so.28
libxerces-c.so libxerces-c.so.28.0 libxerces-depdom.so libxerces-depdom.so.28.0
Any thoughts ? I feel i'm missing something, but don't know what.
Thanks in advance.
run ldd a.out and see if the linker can resolve the right .so file
export LD_LIBRARY_PATH to include the current folder (in the same manner as the PATH variable) and check ldd again
the good way to do what you want is the following one:
g++ test.cpp -Xlinker -R ./xml/xerces-c_2_8_0/lib -lxerces-c -I./xml/xerces-c_2_8_0/include
or
g++ test.cpp -Wl,-rpath ./xml/xerces-c_2_8_0/lib -lxerces-c -I./xml/xerces-c_2_8_0/include
Xlinker or Wl options allow you to use specific linking options, you do not need to modifiy
LD_LIBRARY_PATH
You need to tell the runtime c library where to find the various symbols that arent compiled statically in your code and arent in the usualy /lib and /usr/lib locations.
You do this by adding the path to your shared library to LD_LIBRARY_PATH. In this case, this will be what you have been putting for the -L argument to the compiler.