【发布时间】:2014-02-27 16:12:42
【问题描述】:
我从
阅读了一些关于局部范围静态变量初始化顺序问题的旧文章C++ scoped static initialization is not thread-safe 早在 2004 年,并且
Function Static Variables in Multi-Threaded Environments 2006 年。
然后我开始生成一个示例并检查我的编译器 gcc 4.4.7
int calcSomething(){}
void foo(){
static int x = calcSomething();
}
int main(){
foo();
return 0;
}
objdump 的结果显示:
000000000040061a <_Z3foov>:
40061a: 55 push %rbp
40061b: 48 89 e5 mov %rsp,%rbp
40061e: b8 d0 0a 60 00 mov $0x600ad0,%eax
400623: 0f b6 00 movzbl (%rax),%eax
400626: 84 c0 test %al,%al
400628: 75 28 jne 400652 <_Z3foov+0x38>
40062a: bf d0 0a 60 00 mov $0x600ad0,%edi
40062f: e8 bc fe ff ff callq 4004f0 <__cxa_guard_acquire@plt>
400634: 85 c0 test %eax,%eax
400636: 0f 95 c0 setne %al
400639: 84 c0 test %al,%al
40063b: 74 15 je 400652 <_Z3foov+0x38>
40063d: e8 d2 ff ff ff callq 400614 <_Z13calcSomethingv>
400642: 89 05 90 04 20 00 mov %eax,0x200490(%rip) # 600ad8 <_ZZ3foovE1x>
400648: bf d0 0a 60 00 mov $0x600ad0,%edi
40064d: e8 be fe ff ff callq 400510 <__cxa_guard_release@plt>
400652: c9 leaveq
400653: c3 retq
不幸的是,我对汇编代码的了解非常有限,以至于我不知道编译器在这里做了什么。谁能告诉我,这个汇编代码是做什么的?它仍然不是线程安全的吗?我真的很感谢一些“伪代码”显示 gcc 在这里做什么。
EDIT-1: 正如 Jerry 所说,我启用了 O2 优化,汇编代码是:
0000000000400620 <_Z3foov>:
400620: 48 83 ec 08 sub $0x8,%rsp
400624: 80 3d 85 04 20 00 00 cmpb $0x0,0x200485(%rip) # 600ab0 <_ZGVZ3foovE1x>
40062b: 74 0b je 400638 <_Z3foov+0x18>
40062d: 48 83 c4 08 add $0x8,%rsp
400631: c3 retq
400632: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
400638: bf b0 0a 60 00 mov $0x600ab0,%edi
40063d: e8 9e fe ff ff callq 4004e0 <__cxa_guard_acquire@plt>
400642: 85 c0 test %eax,%eax
400644: 74 e7 je 40062d <_Z3foov+0xd>
400646: c7 05 68 04 20 00 00 movl $0x0,0x200468(%rip) # 600ab8 <_ZZ3foovE1x>
40064d: 00 00 00
400650: bf b0 0a 60 00 mov $0x600ab0,%edi
400655: 48 83 c4 08 add $0x8,%rsp
400659: e9 a2 fe ff ff jmpq 400500 <__cxa_guard_release@plt>
40065e: 66 90 xchg %ax,%ax
【问题讨论】:
-
看起来你编译时没有优化,这会导致一些糟糕的代码,但至少乍一看,它看起来像是线程安全的——
__cxa_guard_acquire看起来像获取互斥体,因此只有一个线程会调用calcSomething。
标签: c++ multithreading gcc assembly static-variables