一个动态库项目,支持 win32 和 arm64 ,编译器是 msvc 和 gcc ( gcc 是自己从源码编译的,版本 15.1.0 ) 对外暴露一个标准 C API ,其内部实现只有一行代码,调用一个内部名称空间内的方法
int my_foo()
{
return internal::bar();
}
魔幻的事情是,这个 so 文件,我写一个控制台程序去调用它,能顺利进入到bar()
中,放到实际项目中bar()
根本就没有被调用,于是尝试打印
int my_foo()
{
std::cout << "111111111111111" << std::endl;
std::cout << __FUNCTION__ << std::endl;
std::cout << "internal::bar address: " << (long long)((void*)&internal::bar);
return internal::bar();
}
好家伙,在 linux 下只能打印前两行,然后函数返回 0 ,但这种情况只发生在项目引用时出现。写一个简单的命令行程序触发完全没问题,win32 下也都没问题。
我想 so 文件已经是二进制了,还能被链接它的程序优化不成?这里卡住了,不知道怎么办
项目均使用了-O2
1
OBJECTION 11 天前 ![]() 要不还是加个-g gdb 进去看看? 根据你的描述看不出来啥原因啊
|
2
zhyl 11 天前 ![]() 只打印前两行会不会是没有 flush 输出缓冲区
|
3
Niunai 11 天前 ![]() 前两行都有 std::endl ,第三行没有。#2 说的没毛病。
|
4
Niunai 11 天前 ![]() 再说了,有没有被优化,反汇编来看看不就行了,有功夫上 V2 来问,没工夫反汇编吗?
猜测完了要验证。 |
![]() |
5
xdeng 11 天前 ![]() 拖到 IDA 里看一下就知道了
|
6
tusj 11 天前 ![]() 你是依据什么判断函数没有被调用的?第 3 行没打印出来,可能是因为你没有 << std::endl;
|
![]() |
7
aqtata OP 没 std::endl 确实,我等下加上。但打印不是问题关键,主要问题时 bar 中的逻辑都没执行,导致接下来其他 api 接口都会调用失败。
但我这里试出来一个解决方法,给 bar 加上一个参数,比如 bar(int x),这样就能进入到 bar 中了,感觉还是和某种优化有关 |
8
Ming5Ming 11 天前 ![]() 既然是一个方法,有没有可能是重载了?
|
![]() |
9
minami 11 天前 ![]() 怀疑优化问题的话可以关闭优化看看。不过盲猜是动态库导出函数调用约定的问题,可以把 internal::bar();提前不要放到 return 里看看,如果能执行就是这个问题了
|
10
Liuuwei 11 天前 via iPhone ![]() 程序都跑完了,缓冲区还会不刷新?
|
11
nooneanyone 11 天前 ![]() 是不是动态链接的问题?
|
12
a83223676 11 天前 ![]() 我会先这么写代码试试
int my_foo() { std::cout << __FUNCTION__ << std::endl; std::cout << "before call bar" << std::endl; int ret = internal::bar(); std::cout << "after call bar.ret:" << ret << std::endl; return ret; } |
13
rtv 11 天前 ![]() 问 ai 回答可能是符号冲突…你回复也说加一个参数就没问题
|
![]() |
14
kita 11 天前 ![]() 你有无 extern "C" {}; 不然可能 link 时候 symbols 不对
|
15
txhwind 11 天前 ![]() 100%是名字冲突了
|
![]() |
16
Ilavena 11 天前 ![]() 首先,你自己写了一个控制台程序取调用它,没有问题,说明动态库是正常的,实际项目里面是否存在 internal::bar 接口影响的?
1 ,在 my_fool 用 exectern C 包装一下,重新编译这个动态库。 2 ,在 linux 下建议你尝试使用 dlopen 加载动态库,以及 dlsym 调用对应接口 这样我觉得问题应该能够解决。 请告诉结果哈 |
![]() |
17
Ilavena 11 天前 ![]() c++还是蛮有魅力的,我搞了 5 年 c++开发,最近再学深度学习,搞 python ,觉得 python 真的简单易学,也觉得 python 真的牛逼。
|
![]() |
18
weidaizi 11 天前 ![]() 1. 首先,使用 -O2 也可以加 -g ,遇到这个情况先 debug ,看看代码到底跑哪里去了
2. 其次,这种简单的问题 99.999999% 不是编译器的问题,所以快去做第 1 件事 3. 如果在项目中调试也是确实没跑进去,建议开个 sanitizer 看看有没有出现未定义的行为 |
19
hwdq0012 11 天前 ![]() 感觉是动态库是旧的,看看编译时间
|
20
cbythe434 11 天前 ![]() internal 命名空间覆盖了吧
|
![]() |
21
yolee599 11 天前 via Android ![]() 你在第三行打印下面再加一行纯文本打印看看,有时候遇到空指针或者其他情况,不会执行打印的
|
22
wanmyj 10 天前 via iPhone ![]() 这个看起来是 rvo 。O2 只是关闭编译器优化,但没有关闭 rvo 。关闭 rvo 有单独的选项的, 加了 fno-elide-constructors 这个参数就 OK 了
|
![]() |
23
jim9606 10 天前 via Android ![]() 会不会是因为混用不同 c/c++运行时导致的?
|
![]() |
24
Gilfoyle26 10 天前 ![]() @Niunai #4 同意!!!
|
26
o0DoO0o 10 天前 ![]() 反汇编应该就可以了,看看 myfoo 返回的是寄存器还是常量 0
|
27
johnnyyeen 10 天前 ![]() 看看 internal::bar();实现,如果 internal::bar();什么也没做,多半被优化了。
|
![]() |
28
aqtata OP |
![]() |
29
aqtata OP ![]() 解决了,是符号冲突了,gcc 默认把所有符号导出了,这点和 msvc 确实不同。
|
![]() |
31
kita 8 天前
@aqtata
https://gcc.gnu.org/wiki/Visibility 你没有看过这篇吧,贴代码要贴全,不然大家盲猜基本上都认为是 symbols 没有 link 对,但是没有办法告诉你哪里没有 link 对 |