【问题标题】:gcc optimization impact on shared library operationgcc 优化对共享库操作的影响
【发布时间】:2023-03-30 08:04:01
【问题描述】:

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

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}

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

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

对应的代码 sn-p:

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 会导致上述详细断言。

【问题讨论】:

  • 所以东西正在被优化掉。哪些东西?没有看到您的代码,我们无法判断。其中可能包含 UB。
  • 程序的写入可能超出了数组的范围,优化可能是重新排列与该数组相邻的变量的布局。
  • 我刚刚在问题中添加了相应的代码。仍有疑问。感谢您的帮助。

标签: c gcc shared-libraries message-queue fpic


【解决方案1】:

我认为这部分来自 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

【讨论】:

  • 从第一个代码块中可以看出,它是使用 -fpic 创建的。
  • 你没有看我写的。正如手册页所建议的那样,我在 lib 创建命令行中没有看到此选项。
  • 感谢您的回复,很抱歉这么晚才回复。 -shared 是一个链接器选项,而 -fpic 是一个编译器选项。上述块中的第一行用于编译,第二行用于链接。手册页 - 据我了解 - 说,链接在一起的不同代码必须以相同的方式编译。在这种情况下,我只有一个来源来形成共享库。
  • 感谢您的回复。我在手册页的 sn-p 中真正认为的是,您应该指定在编译中使用的 -fPIC,当您在构建共享库时使用 -shared 时。同样,这里是关键部分“为了可预测的结果,您还必须在指定此链接器选项时指定用于编译的同一组选项(-fpic、-fPIC 或模型子选项)。”即你错过了-fPIC,我的 2 美分。谢谢!
  • 你是对的,知道我终于看到这说的是你说的。很抱歉很难理解这一点。除此之外问题不是这个。我错误地将一些字节复制到了错误的地方,这并没有导致立即粉碎,而是这种奇怪的行为。改正之后,问题就消失了。再次感谢。
猜你喜欢
  • 2020-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-24
  • 1970-01-01
  • 2012-01-14
相关资源
最近更新 更多