我的代码可以正常工作,但是如果我将项目链接到第三方库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;
}
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)
这可以很好地编译,但是在运行时会出现段错误。如果我删除了行
Abc dummyAbc;
然后一切正常(也就是说,丢失文件或opencv不会有问题)。
如果我检查段错误的堆栈,则会看到:
Thread 1 "my_project" received signal SIGSEGV, Segmentation fault.
0x00007fdea96836b3 in png_destroy_write_struct () from /usr/local/lib/libabc.so
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
。
答案 0 :(得分:3)
我认为这是问题所在吗?
是:很有可能:libabc.so
静态链接了libpng
(可能是其不同版本),并引入了符号冲突。
我不希望openCV看到任何libabc.so导出...我该怎么做?
不能。您必须联系libabc.so
开发人员,并告诉他们隐藏 libpng
符号。
唯一的其他选择(用于单进程执行)是动态加载libabc.so
。
这可以通过dlopen("liabc.so.", RTLD_LOCAL)
完成,甚至可能无法正常工作(具体取决于libabc.so
的链接方式),这可能会导致libabc.so
绑定到您的{ {1}},然后崩溃。
在Linux上,您还可以使用libpng
,它将与其他代码完全隔离dlmopen(LM_ID_NEWLM, "libabc.so", ...)
,并且可以 libabc.so
被链接为包括其所有依赖项(或者您可以将它们显式引入新的加载器命名空间中。)
最后,正如Eljay在这里评论的那样,您可以使用进程间通信,并且具有完全独立的进程负载libabc.so
。与直接使用libabc.so
相比,这样做的性能会差很多,但总比没有好。
答案 1 :(得分:1)
要添加到EmployedRussian的答案中,即使用基于dlmopen
的方法将libabc.so与其余代码隔离:在这种情况下,避免与dlsym
和函数指针混淆,您可以自动生成包装器通过Implib.so获取所需的库函数:
$ cat mysymbols.txt
foo
bar
$ cat mycallback.c
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C"
#endif
// Dlopen callback that loads library to dedicated namespace
void *mycallback() {
void *h = dlmopen(LM_ID_NEWLM, "libabc.so", RTLD_LAZY | RTLD_DEEPBIND);
if (h)
return h;
fprintf(stderr, "dlmopen failed: %s\n", dlerror());
exit(1);
}
$ implib-gen.py --dlopen-callback=mycallback --symbol-list=mysymbols.txt libabc.so
$ ... # Link your app with libabc.tramp.S, libabc.init.c and mycallback.c
答案 2 :(得分:-1)
我会尝试strip
。详情请参见:https://linux.die.net/man/1/strip