Al *_*Wld 2 c++ opencv shared-libraries dynamic-linking dynamic-loading
我的代码工作正常,但如果我将我的项目链接到第三方库libabc.so
(源不可用),那么我突然会遇到分段错误。
我有一个看起来像这样的主程序
#include <opencv2/imgcodecs.hpp>
#include "Abc.h"
int main(int argc, char **argv)
{
Abc dummyAbc;
auto img = cv::imread("dummy.png");
cv::imwrite("123.png", img);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
CMakeList.txt如下
cmake_minimum_required(VERSION 3.1)
set(CMAKE_C_STANDARD 11)
find_package(OpenCV COMPONENTS core highgui imgcodecs)
include_directories(${OpenCV_INCLUDE_DIR})
add_executable(my_project Main.cpp)
target_link_libraries(my_project ${OpenCV_LIBRARIES} abc)
Run Code Online (Sandbox Code Playgroud)
编译良好,但运行时出现段错误。如果我删除该行
cmake_minimum_required(VERSION 3.1)
set(CMAKE_C_STANDARD 11)
find_package(OpenCV COMPONENTS core highgui imgcodecs)
include_directories(${OpenCV_INCLUDE_DIR})
add_executable(my_project Main.cpp)
target_link_libraries(my_project ${OpenCV_LIBRARIES} abc)
Run Code Online (Sandbox Code Playgroud)
然后一切正常(即没有丢失文件或opencv的问题)。
如果我检查段错误的堆栈,我会看到:
Thread 1 "my_project" received signal SIGSEGV, Segmentation fault.
0x00007fdea96836b3 in png_destroy_write_struct () from /usr/local/lib/libabc.so
Run Code Online (Sandbox Code Playgroud)
正在png_destroy_write_struct
被 呼叫cv::imwrite
。
和libpng.so
( libabc.so
!!) 导出png_destroy_write_struct
实际上导出了所有 libpng API(我认为它是静态链接到的?)。我认为这就是问题所在?我不想让 openCV 看到任何导出libabc.so
...我该怎么做?
我尝试使用objcopy --prefix-symbols abc_ libabc.so
但不知何故它没有帮助,现在崩溃发生在abc_png_destroy_write_struct
。
我认为这就是问题所在?
是的:这很可能:libabc.so
具有静态链接(可能是不同版本)libpng
,并引入符号冲突。
我不想让 openCV 看到 libabc.so 导出的任何内容...我该怎么做?
你不能。您必须联系libabc.so
开发人员,并告诉他们隐藏 libpng
符号。
唯一的其他选项(对于单进程执行)是动态加载libabc.so
.
这可以通过 来完成dlopen("liabc.so.", RTLD_LOCAL)
,甚至可能不起作用(具体取决于libabc.so
链接方式)——它可能会导致libabc.so
绑定到您的 版本libpng
,并崩溃。
在 Linux 上,您还可以使用dlmopen(LM_ID_NEWLM, "libabc.so", ...)
它将与代码的其余部分完全隔离,并且如果链接到包含其所有依赖项(或者您可以显式地将它们带入新的加载程序命名空间),则可能会起作用。libabc.so
libabc.so
最后,正如 Eljay 在这里评论的那样,您可以使用进程间通信并拥有完全独立的进程负载libabc.so
。这会比libabc.so
直接使用性能差很多,但总比没有好。