这个电话是从哪里打来的

本文关键字:电话 | 更新日期: 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.ss的地址似乎是作为参数传递的,但由于这是一个简单的指针分配,为什么有必要这样做?

(这种行为似乎发生在很多对指针的赋值中。然而,分配null似乎并不遵循这种模式。)

这个电话是从哪里打来的

猜测:它设置了一点GC卡表,因为您正在创建一个从堆字段到堆对象的新引用。

你说"这种行为似乎发生在很多指向指针的作业中"。这完全符合这个解释。

如果示例中的stringstd::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为您提供了很好的、几乎毫不费力的内存管理。但它不是免费的。无论它在源代码中看起来如何,它绝对不是"一个简单的指针分配"。