如何在每个共享库中使用自己的静态库副本
How to use own copy of static library in each shared library
我有一些无法更改或重建的静态库。该库使用全局变量。像这样:
//lib A
#include <iostream>
static int i = 0;
void printA(){
std::cout << i++ << std::endl;
}
我想创建两个共享库,它们有自己的静态库"副本"及其全局状态:
//lib B
#include "liba.h"
void printB(){
printA();
}
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀��
//lib C
#include "liba.h"
void printC(){
printA();
}
。并同时使用它们:
#include "libb.h"
#include "libc.h"
int main(){
printB();
printB();
printC();
printC();
}
我希望以下输出:
0
1
0
1
.. 但实际上得到:
0
1
2
3
似乎libB
和libC
共享共同的计数器变量。如果可以访问libA
源代码,我会使用 -fvisibility=hidden
重建它。但不幸的是,我只有二进制。
有没有办法在不libA
重建的情况下实现预期的行为?
如果 LibA 使用静态计数器,libB 和 libC 通过调用 printA
来递增,那么如果没有对象文件操作或不可移植的黑客攻击,就无法做你想做的事情。
器在链接时将对全局变量(甚至 static
s(的所有引用解析为同一符号。
如果您愿意操作目标文件,那么以下内容应该适合您:
$ objcopy --prefix-symbols=copy_ liba.a liba-copy.a
#define printA copy_ printA
#include "liba.h"
/* ... */
如果您可以使用 nm
从静态库中获取符号(您将查找的名称将以 <counter name>.<process ID>
的形式(,并且您执行以下操作,那么您可以在运行时读取和写入静态计数器变量:
int counter asm("<counter name>.<process ID>");
counter = 0;
请注意,每次更新库后都必须重复此过程。
您可以复制静态库并重命名所有使用全局状态的符号。 因为符号是用 c++ 编译的,所以你不走运,符号被破坏了。
您可以为所有访问编写一个 C 接口,并重新编译隐藏其符号的静态库,然后使用一些objcopy --prefix-symbols
或g++ -Wl,--wrap=printA
来前缀/重命名 C 符号。
或者您需要事先知道已经损坏的C++名称,然后为库导出的每个符号调用objcopy --redefine-sym _Z6printAv=_Z10printAcopyv
等。
下面是对损坏的名称调用objcopy
的测试设置。我通过检查对象文件、nm a.o
和 nm c.o
找到了符号名称。在这里:
cat <<EOF >Makefile
all: liba.a b.o main.o c.o
# we have access only to liba.a only
objcopy --redefine-sym _Z6printAv=_Z10printAcopyv liba.a libacopy.a
g++ main.o b.o c.o liba.a libacopy.a -o a.out
./a.out
liba.a: a.o
ar rcs liba.a a.o
clean:
rm -fr *.o *.a *.out tmp
EOF
cat <<EOF >a.cpp
#include <iostream>
static int i = 0;
void printA(){
std::cout << i++ << std::endl;
}
EOF
cat <<EOF >b.cpp
void printA();
void printB(){
printA();
}
EOF
cat <<EOF >c.cpp
void printAcopy();
void printC(){
printAcopy();
}
EOF
cat <<EOF >main.cpp
void printB();
void printC();
int main(){
printB();
printB();
printC();
printC();
}
EOF
您可以使用make
编译并运行:
g++ -c -o a.o a.cpp
ar rcs liba.a a.o
g++ -c -o b.o b.cpp
g++ -c -o main.o main.cpp
g++ -c -o c.o c.cpp
# we have access only to liba.a only
objcopy --redefine-sym _Z6printAv=_Z10printAcopyv liba.a libacopy.a
g++ main.o b.o c.o liba.a libacopy.a -o a.out
./a.out
0
1
0
1
- 没有为自己的结构调用列表推回方法
- 基于boost的程序的静态链接——zlib问题
- 类无法访问自己的私有静态 constexpr 方法 - Clang bug?
- 创建自己的owner_ptr类;在传递堆栈或静态分配的地址时如何避免UB?
- 访问另一个类(系统)的非静态字段,就好像它是我自己的字段一样 - 优雅地
- 如何在每个共享库中使用自己的静态库副本
- 链接器没有链接我自己的静态库
- javascript中的静态私有变量用于自己的库
- 如何将 DirectX 库包含在我自己的静态库(独立库)中
- 一个类不能有自己的静态 constexpr 成员实例吗?
- 在您自己的Qt应用程序中使用您自己的静态库
- 在元素自己的析构函数中擦除指向静态向量中元素的指针
- 类自己的类型的静态类成员
- 由于忘记了源文件,在链接我自己的静态库时检测未解析的符号
- 无法链接我自己的静态库
- Linker正在寻找链接到我自己的静态库的静态库
- 链接我自己的静态库时,无法解析的外部符号
- 静态库-使用自己的Qt .so文件的静态库
- 每个文件都有自己的静态变量副本吗?
- 在我自己的操作系统内核上的c++静态构造函数