这个电话是从哪里打来的
本文关键字:电话 | 更新日期: 2023-09-27 18:28:30
我有一些代码与以下代码非常相似:
class C {
string s;
static C a = new C();
static void Main() {
C b = a;
b.s = "hello";
}
在Release模式下,Main
方法的分解如下:
C b = a;
00000000 push ebp
00000001 mov ebp,esp
00000003 push eax
00000004 cmp dword ptr ds:[04581D9Ch],0
0000000b je 00000012
0000000d call 763B3BC3
00000012 xor edx,edx
00000014 mov dword ptr [ebp-4],edx
00000017 mov eax,dword ptr ds:[01B24E20h] ; Everything up to this point
0000001c mov dword ptr [ebp-4],eax ; is fairly clear.
b.s = "hello";
0000001f mov eax,dword ptr ds:[01B22088h] ; Loads the address of "hello"
00000025 mov ecx,dword ptr [ebp-4] ; Loads the address of b
00000028 lea edx,[ecx+4] ; Loads the address of (the reference to?) b.s
0000002b call 76100AE0 ; ??
}
00000030 nop
00000031 mov esp,ebp
00000033 pop ebp
00000034 ret
我不明白为什么在nb打电话是必要的。b.s
和s
的地址似乎是作为参数传递的,但由于这是一个简单的指针分配,为什么有必要这样做?
(这种行为似乎发生在很多对指针的赋值中。然而,分配null
似乎并不遵循这种模式。)
猜测:它设置了一点GC卡表,因为您正在创建一个从堆字段到堆对象的新引用。
你说"这种行为似乎发生在很多指向指针的作业中"。这完全符合这个解释。
如果示例中的string
是std::string
,那么看起来无辜的赋值如下所示:
mov eax, offset "hello"
mov ecx, b
lea edx, [ecx+4] ; edx = &b.s
call std::string::operator=(const char *)
(这个特定的编译似乎期望edx
中的"this"和eax
中的argument——可能是整个程序优化的结果——传统的约定是ecx中的this
和堆栈上的其他argument。)
C++和STL为您提供了很好的、几乎毫不费力的内存管理。但它不是免费的。无论它在源代码中看起来如何,它绝对不是"一个简单的指针分配"。