草庐IT

c++ - 在没有线程支持的程序加载的共享库中使用 C++11 多线程

coder 2023-06-01 原文

我目前正在尝试在加载到 Linux 上的主程序(用 C 编写)的共享库中使用 C++11 多线程。这是一个大型模拟程序的一部分,我无法更改有关库加载的任何内容或一般更改主程序。

主程序是用 gcc 4.1.2 编译的,我没有它的源代码(我不能用 gcc 4.8.2 重新编译它)。

共享库使用 gcc 4.8.2 编译,以便使用 C++11 多线程。我正在传递编译器命令

-pthread -lpthread -std=c++11

What is the correct link options to use std::thread in GCC under linux? 中所述

使用此配置(“-pthread -std=c++11”和 gcc 4.8)编译独立测试程序可以在我的系统上正常工作。但是当我启动加载共享库的程序时,出现异常:

Caught std::exception!
Exception Message: Enable multithreading to use std::thread: Operation not permitted

Terminating...

使用 -pthread-lpthread ( 编辑: 并且只有 -pthread 没有 -lpthread )编译参数不起作用。
编译器参数是(我使用的是 Cook 构建系统):

-pthread -std=c++11 -fmessage-length=0 -fPIC -Wchar-subscripts ...(lots of -W* here)
... -Wunused-variable -m64 -D__64BIT__ -pthread -lpthread

和链接器参数(由于构建系统而导致的重复参数):

-pthread -lpthread -std=c++11 -pthread -lpthread -std=c++11 -shared -fPIC -Wl,-Bsymbolic -Wl,--allow-shlib-undefined -pthread -lpthread

在我的库上调用 ldd 给出以下输出

$ ldd calc3/build/amd64_linux26_RH5/library.so
    linux-vdso.so.1 =>  (0x00007fff4d1fd000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00002ae6ec124000)
    libstdc++.so.6 => /afs/bb/data/d6833/util/gcc_482/lib64/libstdc++.so.6 (0x00002ae6ec340000)
    libm.so.6 => /lib64/libm.so.6 (0x00002ae6ec655000)
    libgcc_s.so.1 => /afs/bb/data/d6833/util/gcc_482/lib64/libgcc_s.so.1 (0x00002ae6ec8d8000)
    libc.so.6 => /lib64/libc.so.6 (0x00002ae6ecaef000)
    /lib64/ld-linux-x86-64.so.2 (0x00000032cb400000)

并在主程序上

$ ldd .../bin-64/main_program
    linux-vdso.so.1 =>  (0x00007fff64595000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00000032cc000000)
    libz.so.1 => /usr/lib64/libz.so.1 (0x00000032cc800000)
    libc.so.6 => /lib64/libc.so.6 (0x00000032cb800000)
    /lib64/ld-linux-x86-64.so.2 (0x00000032cb400000)

pthread 库链接到我的共享库,但不链接到主程序。
answer指出您必须将 pthreads 链接到主程序,但对此答案的第二条评论(@R..)表示没有必要(这听起来合乎逻辑)。

不幸的是,我对整个系统的加载机制一无所知,除了我的库使用另一个 C++ 库作为 API。

请注意,其他 C++11 功能确实有效(并且 libstdc++.so 在我的库的依赖项中)但 C++11 多线程不是(尽管 libpthread.so 也在我的库的依赖项中)。

使用程序本身包含的库中的线程类是有效的(这个线程类似乎也使用 pthreads)。

我也试过用 -fabi-version=0-fabi-version=2因为主程序是用我的库用 gcc 4.1.2 编译的,但它没有改变任何东西。

有什么我忽略的东西或我可以用来使它工作的编译器选项吗?还是好像是我程序环境的问题?欢迎任何想法。

编辑:

我尝试使用 -Wl,-no-as-needed (如评论中所建议)但不幸的是它没有改变任何东西。

使用 clang 3.5 而不是 gcc 4.8 也不起作用。

只要我对主应用程序和共享库使用 gcc 4.8 或 clang 3.5,就可以创建一个加载共享库的小型测试应用程序(如@chill 在下面的答案中所示)工作(即使没有编译器标志)。然而,当主程序使用 gcc 4.1 时,主程序甚至无法加载库(它在我的“真实”应用程序中工作)。我认为编译器的不同 ABI 可能存在问题。

直接从 pthread.h 使用 pthreads似乎工作(虽然程序当前终止于 pthread_join 没有错误消息,但我仍在那里测试......)

编辑 2:

使用 LD_LIBRARY_PATH=$(pwd):$LD_LIBRARY_PATH 运行“测试程序” (因为 gcc 4.8 库路径也需要在那里,谢谢@MvG)确实运行了程序但再次崩溃了 Enable multithreading to use std::thread: Operation not permitted异常(exception)。

我检查了所有其他加载的库(用 strace ./main_program 2>&1 | grep '^open(".*\.so"' [见 here] 找到它们)并用 ldd 检查它们。 .它们都依赖于相同的库(具有相同的路径)。 ldd输出(在所有这些上):

linux-vdso.so.1 =>  (0x00007fff4d3fd000)
libstdc++.so.6 => /afs/bb/data/d6833/util/gcc_482/lib64/libstdc++.so.6 (0x00002ade28774000)
libm.so.6 => /lib64/libm.so.6 (0x00002ade28ab0000)
libgcc_s.so.1 => /afs/bb/data/d6833/util/gcc_482/lib64/libgcc_s.so.1 (0x00002ade28d33000)
libc.so.6 => /lib64/libc.so.6 (0x00002ade28f49000)
/lib64/ld-linux-x86-64.so.2 (0x00000032ea200000)

(除了我的库和另一个库之外,它们都不依赖于 libpthread.so.0(但它是相同的 /lib64/libpthread.so.0 ))

某些库确实有更多的依赖项(似乎与线程无关),但似乎没有任何“冲突”依赖项(在这些库中的任何一个中,对同一库的不同版本/路径都没有依赖项)。

最佳答案

thread.cc 你可以读到如果 __gthread_active_p 会产生这个异常返回假。该调用仅检查给定符号是否可用。有问题的符号是一个弱符号:它不必存在,但会检查它的存在以确定是否支持线程。

但是符号的存在意味着什么?在这种情况下,这意味着该符号位于相关库(在我的情况下为 libgcc_s.so.1)搜索符号定义的符号表列表中。这包括应用程序本身导出的符号,也包括在它之前加载的所有库导出的符号。但是,它不包括之后加载的库。不幸的是,如果 libgcc之前加载 libpthread ,则该符号在其搜索域中不可用。因此它将线程报告为不受支持。我猜你在多线程模块之前加载了一些其他的 C++ 模块,所以你会遇到这个问题。

一种适用于 my reproducing example 的解决方案正在设置 LD_PRELOAD=/lib64/libpthread.so.0在用于调用二进制文件的环境中。加载 libpthread前面,所以它的符号可用于满足弱符号链接(symbolic link)。这不适用于 setuid/setgid 二进制文件,并且在其他情况下也可能被认为是丑陋的黑客,所以我对更清洁的解决方案感兴趣。尽管如此,这在大多数情况下都能完成工作。

关于c++ - 在没有线程支持的程序加载的共享库中使用 C++11 多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20568235/

有关c++ - 在没有线程支持的程序加载的共享库中使用 C++11 多线程的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  10. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

随机推荐