c++ - 通过简单的动态链接来违反一个定义规则
问题描述
问题: ELF 平台上的动态链接 C++ 程序是否总是因违反单一定义规则而处于产生未定义行为的边缘?
更具体:通过简单地编写一个共享库来公开一个函数
#include <string>
int __attribute__((visibility("default"))) combined_length(const char *s,
const char *t)
{
const std::string t1(t);
const std::string u(s + t1);
return u.length();
}
并通过 GCC 7.3.0 编译它
$ g++ -Wall -g -fPIC -shared \
-fvisibility=hidden -fvisibility-inlines-hidden \
-o liblibrary.so library.cpp
operator+()
我创建了一个二进制文件,它为指向字符数组和字符串的指针定义了一个弱符号:
$ readelf -sW liblibrary.so | grep "_ZStpl"
24: 0000000000000ee2 202 FUNC WEAK DEFAULT 12 _ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEPKS5_RKS8_
...
但是看看我得到的标准库二进制文件
$ readelf -sW /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep "_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEPKS5_RKS8_"
2829: 000000000012b1c0 169 FUNC WEAK DEFAULT 13 _ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EEPKS5_RKS8_@@GLIBCXX_3.4.21
这就是我要说的重点:哦,天哪,我库中的符号也应该附有一个版本!
在当前状态下我很好,因为我可以假设标准库二进制文件是使用与我的库相同的头文件构建的。但是如果 libstdc++-v3 的实现者决定定义这个函数的新版本并用 标记它会发生GLIBCXX_3.4.22
什么?由于符号很弱,运行时链接器可以自由决定是采用我的库的未版本化符号还是 libstdc++-v3 的版本化符号。如果我将我的库发送到这样的系统,我会在那里引发未定义的行为。一些符号版本应该为我解决了。
解决方案
推荐阅读
- javascript - 为什么将 window.location.hostname 传递给此条件语句会导致跨域错误?
- python - 在 mkdocs 中添加自定义元数据
- javascript - AG Grid SetColumnSize
- node.js - 如何使用 fetch API 在 nodejs 中使用 Twitter 的搜索 API?
- php - 使用现有数据在数据数组中插入对象列
- java - 如何将 int 解码为 RGBA?
- c# - Net Core:以动态可变的方式将 DTO 包裹在响应模式中
- php - 如何为我对 PHP 的 Android 请求添加 md5 校验和
- php - 使用 Laravel 存储下载和读取大文件
- flutter - 试图将数据发送到第二页