2012-03-19 65 views
-1

我有一些代碼,非常類似於大致如下:這個調用來自哪裏?

class C { 
    string s; 
    static C a = new C(); 

    static void Main() { 
     C b = a; 
     b.s = "hello"; 
} 

Main方法的拆卸,在Release模式,如下:

 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似乎並沒有遵循這個模式。)

回答

5

猜測:它是設置了一下GC卡表,因爲你正在創建從堆字段到堆對象的新引用。

你說過「這種行爲似乎發生在很多指針的分配上」。這完全符合這個解釋。

+0

看起來像是正確的解釋。 MSDN調用該(方法)一個寫屏障。 – 2012-03-19 23:06:03

+0

@HenkHolterman,你能提供一個鏈接嗎? – svick 2012-03-20 13:20:58

+0

[垃圾收集器基礎和性能提示](http://msdn.microsoft.com/zh-cn/library/ms973837.aspx),頁面下半部分 – 2012-03-20 15:53:27

0

如果例子stringstd::string,那麼你無辜的前瞻性的分配是這樣的:

mov eax, offset "hello" 
mov ecx, b 
lea edx, [ecx+4] ; edx = &b.s 
call std::string::operator=(const char *) 

(看來這個具體的編譯預計edx和論點eax「本」 - 可能是整個程序優化的結果 - 傳統的約定是在ecx中的this和堆棧中的其他參數。)

C++和STL爲您提供了很好的並且毫不費力的內存管理。但它不是免費的。這絕對不是「簡單的指針分配」,無論它在源代碼中的外觀如何。

+1

如果它是'std :: string',那麼你將是完全正確的,但這是C#... :) – 2012-03-20 12:07:11