- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
针对 pthread 的静态链接在 Linux 上是一个困难的话题。它曾经将 -lpthread
包装为 -Wl,--whole-archive -lpthread -Wl,--no-whole-archive
(详细信息可以在这个answer)。
效果是符号(对于 pthread)为 strong, not weak 。从 Ubuntu 18.04 左右(gcc 5.4.0 和 gcc 7.4.0 之间)开始,这种行为似乎发生了变化,pthread 符号现在总是最终成为独立于 --whole-archive
选项的弱符号。
因此,-whole-archive
配方停止工作。我的问题的目的是了解工具链(编译器、链接器、标准库)最近发生了什么变化,以及可以采取哪些措施来恢复旧的行为。
示例:
#include <mutex>
int main(int argc, char **argv) {
std::mutex mutex;
mutex.lock();
mutex.unlock();
return 0;
}
在以下所有示例中,都使用了相同的编译命令:
g++ -std=c++11 -Wall -static simple.cpp -Wl,--whole-archive -lpthread -Wl,--no-whole-archive
之前,使用 -static
进行编译时,pthread 符号(例如 pthread_mutex_lock
)很强(被 nm
标记为 T
) ,但现在它们很弱(W
):
Ubuntu 14.04:docker run --rm -it ubuntu:14.04 bash
$ apt-get update
$ apt-get install g++
$ g++ --version
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4
$ nm a.out | grep pthread_mutex_lock
0000000000408160 T __pthread_mutex_lock
00000000004003e0 t __pthread_mutex_lock_full
0000000000408160 T pthread_mutex_lock
Ubuntu 16.04:docker run --rm -it ubuntu:16.04 bash
$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609
$ nm a.out | grep pthread_mutex_lock
00000000004077b0 T __pthread_mutex_lock
0000000000407170 t __pthread_mutex_lock_full
00000000004077b0 T pthread_mutex_lock
Ubuntu 18.04:docker run --rm -it ubuntu:18.04 bash
$ g++ --version
g++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
$ nm ./a.out | grep pthread_mutex_lock
0000000000407010 T __pthread_mutex_lock
00000000004069d0 t __pthread_mutex_lock_full
0000000000407010 W pthread_mutex_lock
总结一下:
T pthread_mutex_lock
(强符号)W pthread_mutex_lock
(弱符号)在更复杂的示例中,这可能会导致段错误。例如,在这段代码中(未修改的文件可以在 here 中找到):
#include <pthread.h>
#include <thread>
#include <cstring>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
std::mutex mutex;
void myfunc(int i) {
mutex.lock();
std::cout << i << " " << std::this_thread::get_id() << std::endl << std::flush;
mutex.unlock();
}
int main(int argc, char **argv) {
std::cout << "main " << std::this_thread::get_id() << std::endl;
std::vector<std::thread> threads;
unsigned int nthreads;
if (argc > 1) {
nthreads = std::strtoll(argv[1], NULL, 0);
} else {
nthreads = 1;
}
for (unsigned int i = 0; i < nthreads; ++i) {
threads.push_back(std::thread(myfunc, i));
}
for (auto& thread : threads) {
thread.join();
}
}
尝试生成静态二进制文件失败,例如:
$ g++ thread_get_id.cpp -Wall -std=c++11 -O3 -static -pthread -Wl,--whole-archive -lpthread -Wl,--no-whole-archive
$ ./a.out
Segmentation fault (core dumped)
我尝试删除-O3
、切换到clang++
、切换到Gold链接器等。但它总是崩溃。根据我的理解,静态二进制文件崩溃的原因是基本函数(例如pthread_mutex_lock)最终没有成为强符号。因此,它们在最终的二进制文件中丢失,导致运行时错误。
除了 Ubuntu 18.04 之外,我还可以使用 gcc 10.0.0 在 Arch Linux 上重现相同的行为。但是,在 Ubuntu 14.04 和 16.04 上,可以创建并执行静态二进制文件,不会出现任何错误。
问题:
最佳答案
新解决方法:-Wl,--whole-archive -lrt -lpthread -Wl,--no-whole-archive
正如 Federico 所指出的,添加 -lrt
可以防止崩溃。整个问题几乎肯定与 librt(实时扩展库)有关。它的计时函数(例如clock_gettime
、clock_nanosleep
)用于实现线程。
在 Ubuntu 16.04 和 18.04 之间,与这些功能相关的 glibc 也发生了变化。具体细节我没看懂,不过代码中有注释:
/* clock_nanosleep moved to libc in version 2.17; old binaries may expect the symbol version it had in librt. */
还有更新的提交消息:
commit 79a547b162657b3fa34d31917cc29f0e7af19e4c
Author: Adhemerval Zanella
Date: Tue Nov 5 19:59:36 2019 +0000nptl: Move nanosleep implementation to libc
Checked on x86_64-linux-gnu and powerpc64le-linux-gnu. I also checked the libpthread.so .gnu.version_d entries for every ABI affected and all of them contains the required versions (including for architectures which exports __nanosleep with a different version).
总而言之,解决方法是添加-lrt
。请注意,在某些示例(不是此处)中,顺序是相关的。从 gcc 中的测试和其他一些讨论中,我得到的印象是,首先链接 librt 会导致比 pthread 之后链接更少的问题。 (在一个示例中,似乎只有 -lpthread -lrt -lpthread
有效,但尚不清楚原因。)
关于c++ - GCC: --whole-archive 静态链接到 pthread 的方法在最近的 gcc 版本中停止工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58848694/
有没有办法从 archive.org 上传或触发自己网站的快照到 WayBackMachine?我已经检查了常见问题解答和 archive.org API,但找不到任何使用脚本触发此问题的方法。 最佳
在我当前的项目中,我正在集成 RestKit 库(我不知道它是否重要),当我使用编译器提示的“存档”时尝试交付应用程序进行测试 "RestKit/RestKit.h" is not found 在构
在我的项目开始时,有两个 terraform 模块:base 和 reusable_module。 base/main.tf # Provide abstraction to define a lam
我试图弄清楚如何以正确的方式构建我的 Cocoa 应用程序的发布版本。 到目前为止,我已经使用了 为归档而构建 选项,并从 Xcode 的 DerivedData 文件夹深处获取应用程序包。 今天我试
我有一个 Swift 语言的 iOS 项目,我必须在终端上使用命令创建存档和 .ipa。 我正在使用 Github 操作在试飞中上传 iOS 版本。 我正在遵循此链接中提到的所有说明: https:/
我正在使用 GCC 从两个 *.a(静态库)创建一个共享对象库。我引用了这些文章: How to force gcc to link an unused static library How to i
我的应用程序突然停止创建 iOS App Archive,而是开始创建 Xcode Generic Archive。 这是在为我的应用程序的新版本进行更改后发生的,我添加了逻辑、UI 更改和一些新框架
我有一个包含大约 800 个 .tgz 文件的目录,每个文件包含大约 10 个文件。实际上,我想将每个存档转换为同名目录。是否有一个简单的一行命令来执行此操作,还是我应该编写一个脚本? 最佳答案 自
在 gcc 中使用 -Wl--whole-archive ... -Wl--no-whole-archive 标志时,您如何验证库内部的所有内容都正确链接?另外,您如何验证该库是否可以调用由 LD_L
我有一个用 Swift 编写的小型命令行应用程序,现在我想将其归档。然而,像我之前的许多其他人一样,我遇到了如何将 Archive Type 从 Generic Xcode Archive 更改为 M
我不确定是否应该对 .emacs.d 下的以下文件进行版本控制: [lucas@lucas-ThinkPad-W520]/home/lucas/.emacs.d$ file elpa/archives
我正在处理 Postgres DVD tutorial并且在导入示例数据库时遇到问题。 运行 pg_restore -U postgres -d dvdrental ~[filepath]/dvd-d
注意: Boost 的存档方案基于对称的输入和输出存档类。一直写这两者很乏味,所以我将使用 ?archive 来表示 oarchive 和 iarchive。 总结: 将自定义存档的基类从 binar
是否可以使用 Node.js 流构建一个 zip 存档,并在创建时通过对 HTTP GET 请求的响应将该 zip 存档提供给客户端/用户?我正在寻找一种最好避免将整个 zip 缓冲到服务器内存中的解
我正在尝试使用 XCODE 4.3.1 发布一个临时 ipa。归档我的 iOS 应用程序时,我可以在管理器中看到归档类型是“Mac App Archive”,虽然我知道它应该是“iOS App Arc
我正在参加 Udacity 的类(class),该类(class)要求我在我的系统上设置虚拟机。我已经下载并安装了 Virtual Box 和 Vagrant。当我尝试运行命令 vagrant up
我试图找到一个很好的例子来说明如何使用这些二进制宽字符版本的 boost 序列化内容。我拼凑了一些代码来尝试让它工作,但不幸的是,我在尝试编译它时遇到了链接器错误的轰炸。 这是我的代码,以防我做任何明
目标与问题 我在 IntelliJ 中创建了一个 Java 程序。我按照说明将其构建为 .jar 文件 here 。当我尝试运行它时,它给出以下输出: Parameters: archive-name
我已包含在 hector-core-1.1-2 文件夹中找到的所有 jar。还有其他我没有包含的 jar 吗?我尝试过的事情。1)清除netbeans缓存2)下载org.apache.xbean.fi
我正在尝试打开包含创建数据库和 INSERT 语句的 PostgreSQL 的 SQL 脚本(.sql 文件),但是当我尝试使用 PgAdmin 4 恢复数据库时,它给我错误提示“pg_restore
我是一名优秀的程序员,十分优秀!