11

The problem is I use dlopen to load a library (the .so is written by me, it's not a system library), but I got the error shown in the title.

  1. I have included dlfcn.h
  2. in compiler, I used the -ldl command
  3. What I want to load is just the source code folder, I tried to add -L., but it did not work.
Cœur
  • 37,241
  • 25
  • 195
  • 267
user1534282
  • 635
  • 1
  • 6
  • 7

5 Answers5

15

The most brutal and effective way to find out where your code goes wrong is the following command which will activate the debugging mode for shared libraries and is documented here:

export LD_DEBUG=libs

Then, you will be surprised that so much information pops up. Don't worry, these information tells you which shared libraries the command you just typed needs and where to locate these needed libraries. For example, if you type reset, the screen will be reseted and then information about the shared libraries reset command needs will be printed.

Then, execute your "problematic" executable to see what's going wrong.


PS.1 : According to your accepted mythagal's solution :

Specify the full path to the file in dlopen

dlopen("/full/path/to/libfile.so");

It seemed that even though you use absolute or relative path in the dlopen function, the directory not found error will still show up. I am using CentOS, and my Debian is also having this problem. So I think the first solution mythagal provide is wrong. You can verify that in the "debugging" mode I mentioned above.


PS.2: If you "install" or "compile" a shared library rather than install it through package manager, you MUST run sudo ldconfig /path/where/not/found/shared/library/reside to notify the system of the newly added shared library. For example :

cp /etc/ld.so.cache ~/ld.so.cache.backup    
#cp -r /etc/ld.so.conf.d ~/ld.so.conf.d.backup #sometimes this backup is unnecessary.
#cp /etc/ld.so.conf ~/ld.so.conf.backup #sometimes this backup is unnecessary.
sudo ldconfig /PATH/WHERE/NOT/FOUND/SHARED/LIBRARY/RESIDE
###I am omitting the cp commands to roll back.
###For example, sudo cp -f ld.so.cache /etc/ld.so.cache

To understand what's going on here, please carefully read all the contents in the link above.


PS.3 : You can always use the command export LD_DEBUG=help,export LD_DEBUG=libs to figure out how -rpath or LD_LIBRARY_PATH solve your problem. You will love this debugging mode.


PS.4: A less brutal way to figure out what's going wrong:

ldd ./YOURproblematicEXECUTABLE

This command can tell you whether your shared library to be opened is located or not. Besides, there are so many ways to fix your problem and each way has its limitation and application. So I strongly suggested you read the link I provide you above and understand how to choose the way to solve your problem. After reading that, if you actually feel like being very "OK", you can also read this Better understanding Linux secondary dependencies solving with examples for deeper understanding.

Han XIAO
  • 1,148
  • 9
  • 20
9

If the library you want to dlopen is not in the standard search path you have a number of options:

  1. Specify the full path to the file in dlopen

    dlopen("/full/path/to/libfile.so");

  2. Add the path to the library via LD_LIBRARY_PATH

    LD_LIBRARY_PATH=/path/to/library/ ./executable

  3. use the ld -rpath option to add a library path to the application.

    g++ -link stuff- -Wl,-rpath=/path/to/library/

Note that options 1 & 3 hardcode the library path into your application. -rpath does have an option to specify a relative path, i.e.

-Wl,-rpath=$ORIGIN/../lib/

Will embed a relative path into the application.

mythagel
  • 1,789
  • 19
  • 15
  • It not work,I watch the file type: so is ELF 32-bit LSB shared object, ARM,but executable file is ELF 32-bit LSB executable, Intel 80386,is it the platform problem? – user1534282 Oct 12 '12 at 02:22
  • Both the executable and library must be compiled for the same platform, yes. – mythagel Oct 12 '12 at 02:27
2

the dlopen's declaration look like, void *dlopen(const char *filename, int flag);

if you set the para 'filename' as shared library's name , you should add you current path into the 'LD_LIBRARY_PATH'.for instance,

1, dlopen("libtest.so" , RTLD_LAZY)

2, in shell , export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

bbg
  • 321
  • 1
  • 6
2

I would recommed dlerror to get the reason

void* handle = dlopen(SO_FILE, RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND);
if(handle == NULL)
{
    printf(LOG_ERROR, "Error: %s\n",  dlerror());
    assert(0);
}

this will report detailed reason for the error

Yongqi Z
  • 605
  • 8
  • 20
1

For my case, the solution was very simple:

The path is expected to be absolute unless clearly specified as relative

So I replaced

dlopen("mylib.so", RTLD_NOW)

with

dlopen("./mylib.so", RTLD_NOW)

And the problem solved.

ar2015
  • 5,558
  • 8
  • 53
  • 110
  • 1
    Though in my case the problem was not same, but after trying to use RTLD_NOW had shown the problem at hand. I initially tried LD_DEBUG-libs, it was chatty yet no useful info for me as I was using RTLD_LAZY mode for opening and it didn't complain about a missing definition in the library. But when I used RTLD_NOW flag along with LD_DEBUG=libs, as a first bottom most line, it had shown which cpp virtual function isn't implemented. – BaskarA May 27 '23 at 06:54