在ctypes加载的共享库中卸载共享库

2024-07-04 16:19:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我从python脚本调用一个so文件。据我所知,我并不需要释放在python中使用ctype打开的共享库。但是dlt()不会在我的代码中打开另一个文件。 在这种情况下,从python端使用是否安全?难道我不需要释放在ctypes loade so文件中打开的共享库吗?在


Tags: 文件代码脚本so情况ctypectypesdlt
1条回答
网友
1楼 · 发布于 2024-07-04 16:19:13

规则在您自己之后清理总是适用的(尽管现代技术为您解决了清洁方面的问题)。在

[Python 3.5]: ctypes - A foreign function library for Python包含很多有用的信息,应该是你的朋友。在

ctypes在加载.dll时使用dlopen。正如我所注意到的,它不调用相应的dlclose,这意味着.dll(以及加载时加载的所有依赖项)将保留在内存中,直到进程终止(或显式卸载)。在

[man7]: DLOPEN(3)

If the object specified by filename has dependencies on other shared objects, then these are also automatically loaded by the dynamic linker using the same rules. (This process may occur recursively, if those objects in turn have dependencies, and so on.)
...
If the same shared object is loaded again with dlopen(), the same object handle is returned. The dynamic linker maintains reference counts for object handles, so a dynamically loaded shared object is not deallocated until dlclose() has been called on it as many times as dlopen() has succeeded on it. Any initialization returns (see below) are called just once.

所以,我认为你不会有问题(当然,一切都取决于上下文)。正如您所注意到的,多次加载一个库并不是每次都加载它,因此耗尽内存的机会非常小(除非您加载大量不同的.dll,每个都有很多不同的依赖项)。在

我能想到的一个例子是加载一个使用另一个.dll的符号的.dll。如果该符号也在之前加载的另一个(3rd.dll中定义,则代码的行为将与预期不同。在

无论如何,您可以手动卸载(或者更好:减少其refcount)a.dll(我不确定这如何符合推荐的方法最佳实践),如下例所示。在

dll.c

#include <stdio.h>


int test() {
    printf("[%s] (%d) - [%s]\n", __FILE__, __LINE__, __FUNCTION__);
    return 0;
}

代码.py

^{pr2}$

输出

[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q052179325]> ls
code.py  dll.c
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q052179325]> gcc -fPIC -shared -o dll.so dll.c
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q052179325]> python3 ./code.py
Python 3.5.2 (default, Nov 23 2017, 16:37:01)
[GCC 5.4.0 20160609] on linux

Loading a dll via `ctypes`, then delete the object. The dll is not unloaded. Call `dlclose` to unload. A 2nd call will fail.
<CDLL './dll.so', handle 1d7aa20 at 0x7fa38715f240>
dlclose returned 0
dlclose returned -1

Use `ctypes` to load the dll twice. The dll is not actually loaded only the 1st time (both have the same handle), but its ref count is increased. `dlclose` must be also called twice.
<CDLL './dll.so', handle 1de2c80 at 0x7fa38715f240>
<CDLL './dll.so', handle 1de2c80 at 0x7fa38715f278>
dlclose returned 0
dlclose returned 0
dlclose returned -1

Load a dll via `ctypes`, and load one of its funcs. Try calling it before and after unloading the dll.
<CDLL './dll.so', handle 1de39c0 at 0x7fa38715f8d0>
[dll.c] (5) - [test]
test returned 0
dlclose returned 0
Segmentation fault (core dumped)

相关问题 更多 >

    热门问题