我有这样的代码:
struct Storage
{
static int GetData()
{
static int global_value;
return global_value++;
}
};
int free_func()
{
static int local_value;
return local_value++;
}
int storage_test_func()
{
return Storage::GetData();
}
在 OSX 上编译它:
$ clang++ 1.cpp -shared
并运行 nm:
$ nm | c++filt
我得到了奇怪的结果:
0000000000000f50 T storage_test_func()
0000000000000f30 T free_func()
0000000000000f60 unsigned short Storage::GetData()
0000000000001024 bool free_func()::local_value
0000000000001020 D Storage::GetData()::global_value
U dyld_stub_binder
两个符号(local_value
和global_value
)有不同的链接!一个明显的区别是 global_value
是在静态成员函数中定义的,而 local_value
是在自由函数中定义的。
有人能解释一下为什么会这样吗?
更新:
阅读评论后,我似乎应该澄清一些事情。
也许使用 c++filt
是个坏主意。没有它显示:
$ nm
0000000000000f50 T __Z17storage_test_funcv
0000000000000f30 T __Z9free_funcv
0000000000000f60 t __ZN7Storage7GetDataEv
0000000000001024 b __ZZ9free_funcvE11local_value
0000000000001020 D __ZZN7Storage7GetDataEvE5value
U dyld_stub_binder
是的。 __ZZ9free_funcvE11local_value
转到 BSS,__ZZN7Storage7GetDataEvE5value
转到数据部分。
man nm
说:
If the symbol is local (non-external), the symbol's type is instead represented by the corresponding lowercase letter.
这就是我所看到的。 __ZZ9free_funcvE11local_value
用小写b
标记,__ZZN7Storage7GetDataEvE5value
用大写D
标记。
这是问题的主要部分。为什么会这样?
UPD2 另一种方式:
$ clang++ -c -emit-llvm 1.cpp
$ llvm-dis 1.bc
显示这些变量在内部是如何表示的:
@_ZZ9free_funcvE11local_value = internal global i32 0, align 4
@_ZZN7Storage7GetDataEvE5value = global i32 0, align 4
UPD3
还有一些关于符号所属的不同部分的担忧。将 __ZZ9free_funcvE11local_value
放入文本部分不会改变其可见性:
struct Storage
{
static int GetData()
{
static int value;
return value++;
}
};
int free_func()
{
static int local_value = 123;
return local_value++;
}
int storage_test_func()
{
return Storage::GetData();
}
编译:
$ clang++ 1.cpp -shared
检查:
$ nm
给予:
0000000000000f50 T __Z17storage_test_funcv
0000000000000f30 T __Z9free_funcv
0000000000000f60 t __ZN7Storage7GetDataEv
0000000000001020 d __ZZ9free_funcvE11local_value
0000000000001024 D __ZZN7Storage7GetDataEvE5value
现在两个符号都在数据部分,但仍然其中一个是本地,另一个是全局。 问题是为什么会发生?有人可以了解此类编译器决策的逻辑吗?
最佳答案
静态成员函数中的局部静态变量与自由函数中的局部静态变量没有区别。
Two symbols (local_value and global_value) have different linkage!
在标准命名法中,从标准的角度来看,这两个变量没有联系。
函数之间的相关区别不在于一个是静态成员函数而另一个不是。相关的区别是前者是一个内联函数,而后者不是。
非内联函数只能在一个翻译单元中定义,因此它们的局部静态变量不需要从其他翻译单元访问。
另一方面,内联函数必须在使用它们的每个翻译单元中定义。而且,由于局部静态必须在全局范围内引用同一个对象,因此该对象必须对多个翻译单元可见。
关于c++ - 自由函数中静态变量与静态成员函数的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36952516/