obj.CurrSize -= size;
0x00000000003ad2d7 <+183>: mov eax,0x0
0x00000000003ad2dc <+188>: test rax,rax
0x00000000003ad2df <+191>: je 0x3ad2e6 <+198>
0x00000000003ad2e1 <+193>: call 0x0
0x00000000003ad2e6 <+198>: mov rax, 0xffffffffffffff60
0x00000000003ad2ed <+205>: sub rbx,r15
0x00000000003ad2f0 <+208>: add QWORD PTR fs:[rax],rbx`
为什么要测试零,如果为零,则跳过一条指令,否则也会这样做?
答案 0 :(得分:2)
阅读一个不相关的问题exposes a pattern that looked similar to yours,我想我找到了你的奇怪代码的来源。
很可能这段代码来自与线程相关的C ++ 11功能的扩展,特别是使用__gthread_active_p()
检查pthread
库是否实际链接的内容。
大多数可能处理libstdc ++中的线程问题的代码(但在没有线程支持的情况下有合理的回退)会被
所困扰if(__gthread_active_p())
反过来通常归结为检查符号__pthread_key_create
是否定义为与NULL
不同的内容。这里的技巧是这样的函数声明与__attribute__ ((weak))
,所以,如果没有提供定义(即如果pthread
库没有链接),而不是抱怨,链接器只是将其引用解析为NULL。
因此,您在代码中看到的是编译器留下来执行线程相关内容的检查(比如,获取保护某些共享资源的互斥锁)。预链接代码可能类似于:
mov eax,__pthread_key_create
test rax,rax
jz .skip_mutex_init
call __pthread_init_some_mutex
.skip_mutex_init:
mov rax, 0xffffffffffffff60
sub rbx,r15
add QWORD PTR fs:[rax],rbx`
您可以看到解析为__pthread
指针的所有NULL
符号。当然,生成的代码非常愚蠢 - 编译器无法知道链接器是否将使用-lpthread
进行调用,而链接器只执行愚蠢的替换 - 它运行起来太迟了优化器再次启动(除非LTO已启用,但这是一个完全不同的游戏)。
您可以看到类似的模式playing with the compiler explorer:尝试启用/禁用链接完整二进制文件(右侧带有11010标题的按钮),以及在命令行上添加/删除-pthread
。
现在,我没有设法重现您的结果,但可能来自使用的libstdc++
的不同版本,或者代码中使用了不同的线程感知组件(我刚试过使用std::mutex
和std::shared_ptr
)。