2010-03-12 34 views
8

Başlık kinda her şeyi söylüyor. Her zamanki SOS komutu ! Bpmd bir isim olmadan çok iyi bir şey yapmaz.WinDbg anonim bir yöntemle nasıl kırılır?

bazı fikirler vardı:

  • dökümü her yöntem, daha sonra kullanmak bpmd Eğer gerçek dünyadaki kullanımlarda
    • pratik değil tekabül MethodDesc bulunca -md Ne söyleyebilirim gelen . Dökümü anonim tip/yöntemlerle sınırlamak için bir makro yazmış olsam bile, bunları birbirinden ayırmanın açık bir yolu yoktur.
  • kullanım Reflektör dinamik meclisleri ve/veya Reflection.Emit ile uğraşırken
    • yardımcı olmuyor MSIL Adını dökümü. Bu tür senaryolarda içindeki yerel değişkenler okumak için Visual Studio'nun, yetersizlik
  • o vurmak için o zaman, change to Windbg using the noninvasive trick
    • bekleyin VS kesme noktası ayarlamak ... Ben ilk etapta WinDbg döndü bütün nedendir VS den ayırma girişiminde (app ile birlikte) asmak için neden olur. Bunun nedeni, yönetilen hata ayıklayıcının standart bir "sabit" hata ayıklayıcısı yerine "soft" debugger via thread injection olmasıdır. Ya da belki sadece Silverlight'a özgü bir VS hatasıdır (neredeyse ilk I've encountered).
  • eğer doğrusu buna çare istemem gerçi, o zaman,
    • benim yedek planında yol tek adıma anonim yöntem haline dönmesini bilinen başka bir yere kesme noktası ayarlamak bu Q & bir daha iyi bir yol
+0

Not: WinDbg'yi gereksiz kılan bir rastlantısal keşif yaptım. Dinamik derleme oluşturma sırasında DebuggableAttribute (http://msdn.microsoft.com/en-us/library/system.diagnostics.debuggableattribute.aspx) programsal olarak yayarsanız, Visual Studio'daki yerel varlıkları yalnızca iyi görebilirsiniz. . –

cevap

9

anonim yöntem gerçekten anonim değil ortaya koymaktadır. Sadece bir derleyici oluşturulmuş ismin arkasına saklanıyor.

bu küçük örneği inceleyelim:

Func<int, int> a = (x) => x + 1; 

Console.WriteLine(a.Invoke(1)); 

dönüş değerini bulmak için, yöntem uygulanması adını bulmalıyız. Bunu yapmak için, çevredeki yöntemin MethodDesc'ini bulmamız gerekir. Bu örnekte o kadar, Main() geçerli:

0:000> !name2ee * TestBench.Program.Main 
Module: 6db11000 (mscorlib.dll) 
-------------------------------------- 
Module: 00162c5c (TestBench.exe) 
Token: 0x06000001 
MethodDesc: 00163010 
Name: TestBench.Program.Main() 
JITTED Code Address: 001e0070 

MethodDesc Via biz Main()

0:000> !dumpil 00163010 
ilAddr = 003f2068 
IL_0000: nop 
IL_0001: ldstr "press enter" 
IL_0006: call System.Console::WriteLine  
IL_000b: nop 
IL_000c: call System.Console::ReadLine 
IL_0011: pop 
IL_0012: ldsfld TestBench.Program::CS$<>9__CachedAnonymousMethodDelegate1 
IL_0017: brtrue.s IL_002c 
IL_0019: ldnull 
IL_001a: ldftn TestBench.Program::<Main>b__0 
IL_0020: newobj class [System.Core]System.Func`2<int32,int32>::.ctor 
IL_0025: stsfld TestBench.Program::CS$<>9__CachedAnonymousMethodDelegate1 
IL_002a: br.s IL_002c 
IL_002c: ldsfld TestBench.Program::CS$<>9__CachedAnonymousMethodDelegate1 
IL_0031: stloc.0 
IL_0032: ldloc.0 
IL_0033: ldc.i4.1 
IL_0034: callvirt class [System.Core]System.Func`2<int32,int32>::Invoke 
IL_0039: call System.Console::WriteLine 
IL_003e: nop 
IL_003f: ret 

Bildirimi komik görünümlü isimler için IL dökümü. Oluşturma delegesi türünün ve gerçek yöntemin adlarıdır. Metot, <Main>b__0 olarak adlandırılmaktadır. Şu yönteme bakalım:

0:000> !name2ee * TestBench.Program.<Main>b__0 
Module: 6db11000 (mscorlib.dll) 
-------------------------------------- 
Module: 00152c5c (TestBench.exe) 
Token: 0x06000003 
MethodDesc: 00153024 
Name: TestBench.Program.<Main>b__0(Int32) 
Not JITTED yet. Use !bpmd -md 00153024 to break on run. 

Burada var. MethodDesc 00153024 ve yorum olarak, MethodDesc kullanarak kesme noktasını ayarlamak için bpmd kullanabilirsiniz.bulma

+2

+1 Harika cevap, çok titiz. –

0

"Eğer <> ...." adı senaryonuz için zor olduğunu, nasıl düzenli bir yöntem yapma konusunda? Bu genellikle çok basittir; Sadece zor şey değişkenleri yakalanır ancak bu çok kötü değil - örneğin bu aynı şeyi yapmak:

static void Main() 
    { 
     List<int> list = new List<int> { 1, 2, 3, 4, 5 }; 
     int div = 2; 
     foreach (var item in list.Where(x => x % div == 0)) 
     { 
      Console.WriteLine(item); 
     } 

     ListSearcher ls = new ListSearcher(); 
     ls.div = 2; 
     foreach (var item in list.Where(ls.Test)) 
     { 
      Console.WriteLine(item); 
     } 
    } 
    class ListSearcher 
    { 
     public int div; 
     public bool Test(int x) 
     { 
      return x % div == 0; 
     } 
    } 
0

için yöntem açıklayıcısı eylem noktaları döker. Yol Tarifi here.

+0

Merhaba Igor, bu konuyla ilgili bölümleri dahil değil, sadece bağlantı sadece bir cevaptır. –

İlgili konular