c - gcc 优化对共享库操作的影响

标签 c gcc shared-libraries message-queue fpic

我有一个自己的共享库,编译和链接如下:

gcc -g -Wall -fpic -c -o cont.o cont.c
gcc -g -shared -o libcont.so cont.o -lrt

我有一个使用此库的程序(nr):

gcc -g -Wall -I/include_path -c -o nr.o nr.c
gcc -L/shared_lib_path nr.o -lcont -o nr

如果调用共享库的函数之一,则可能会调用 POSIX 消息发送 (mq_send()),这可能会导致断言错误。 strace ./nr 对此做了如下说明:

) = 1 (in [5])
mq_timedreceive(5, "\17\0ryName\0stester\0\t\0op\0srate\0\22\0ro"..., 2000, 0, NULL) = 76
mq_open("tester_asdf", O_WRONLY|O_NONBLOCK) = 6
writev(2, [{"Inconsistency detected by ld.so:"..., 33}, {"dl-lookup.c", 11}, {": ", 2}, {"167", 3}, {": ", 2}, {"check_match", 11}, {": ", 2}, {"Assertion `", 11}, {"version->filename == ((void *)0)"..., 79}, {"' failed!\n", 10}], 10Inconsistency detected by ld.so: dl-lookup.c: 167: check_match: Assertion `version->filename == ((void *)0) || ! _dl_name_match_p (version->filename, map)' failed!
) = 164

非常有趣的是,如果我使用默认级别以外的任何优化级别(例如 -O3)来编译程序,一切都会正常工作:

gcc -g -Wall -O3 -I/include_path -c -o nr.o nr.c
gcc -L/shared_lib_path nr.o -lcont -o nr

在这种情况下strace ./nr说:

) = 1 (in [5])
mq_timedreceive(5, "\17\0ryName\0stester\0\t\0op\0srate\0\22\0ro"..., 2000, 0, NULL) = 76
mq_open("tester_asdf", O_WRONLY|O_NONBLOCK) = 6
mq_timedsend(6, "\t\0op\0srate\0\22\0root\0scall_rating\0\t"..., 59, 0, NULL) = 0
mq_timedreceive(5, "\t\0op\0srate\0\22\0root\0scall_rating\0\t"..., 2000, 0, NULL) = -1 EAGAIN (Resource temporarily unavailable)
pselect6(6, [5], NULL, NULL, NULL, {~[INT ILL BUS FPE KILL SEGV ALRM TERM STOP RTMIN], 8}

这正是我所期望的独立于优化级别的结果。

造成这种情况的可能原因是什么?

相应的代码片段:

fprintf(stderr, "mqFd: %d, msg: %p, size: %d\n", (int)mqFd, msg, (int)size);
mq_send(mqFd, msg, size, 0);

fprintfmq_send 之前打印:

mqFd: 6, msg: 0x7ffdadef1820, size: 59

这很好,但是调用 mq_send 会产生上述详细的断言。

最佳答案

我认为 gcc 手册页中的这部分可能与您所看到的内容相关:

   -shared
       Produce a shared object which can then be linked with other objects to form an executable.
       Not all systems support this option.  For predictable results, you must also specify the
       same set of options used for compilation (-fpic, -fPIC, or model suboptions) when you
       specify this linker option.[1]

这意味着,您需要将 -fpic 添加到库创建的命令行中。

关于c - gcc 优化对共享库操作的影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40091267/

相关文章:

c - 尝试编写一个程序来求和一个 int 和一个 char 的值

struct 的 c 指针在执行时导致段错误

从程序集调用 C mainCRTStartup 函数(MASM 兼容)

c++ - 在自定义库位置的情况下使用 dlopen 加载依赖库

c++ - 将共享库与 CMake 链接

c - 如何在 Rust 中使用编译的 C .so 文件

c - 放弃 OpenCL 中额外全局工作 ID 的计算

linux - ELF 动态加载程序符号查找顺序

c++ - 当 std::uint_fast32_t 在 GCC 中为 4 字节时,std::mt19937 失败

c++ - 如何让 cmake 使用 "-pthread"而不是 -lpthread”?