2014-09-16 13 views
7

मेरे पास आउटऑफमेमरी अपवाद है और मैं आकार और सरणी के प्रकार का विश्लेषण करना चाहता हूं जो बनाया जाएगा।सरणी प्रकार की पहचान कैसे करें?

मुझे लगता है कि स्थिति के लिए एक डेमो उद्देश्य डंप बनाया गया है और मैं निम्नलिखित जानकारी प्राप्त करने में सक्षम हूँ:

0:000> !pe 
Exception object: 023f389c 
Exception type: System.OutOfMemoryException 
Message: <none> 
InnerException: <none> 
StackTrace (generated): 
    SP  IP  Function 
    0015EE44 0099007F OOM2!OOM2.Program.Main()+0xf 

StackTraceString: <none> 
HResult: 8007000e 

0:000> !u 0099007F 
Normal JIT generated code 
OOM2.Program.Main() 
Begin 00990070, size 22 
00990070 baffffff7f  mov  edx,7FFFFFFFh 
00990075 b90241a478  mov  ecx,offset mscorlib_ni+0x4102 (78a44102) 
0099007a e8192194ff  call 002d2198 (JitHelp: CORINFO_HELP_NEWARR_1_VC) 
>>> 0099007f 8bc8   mov  ecx,eax 
... 

तो मैं देख सकता हूँ कि एक नई सरणी बनाई गई है और आकार 7FFFFFFF है, जो है 2 अरब आइटम (कृपया इस तथ्य को अनदेखा करें कि आप उस आकार के बाइट [] को 32 बिट .NET अनुप्रयोग में भी नहीं बना सकते हैं, इसलिए इस उदाहरण में टाइप शायद कोई फर्क नहीं पड़ता।)

मैंने अब पढ़ा है सरणी का प्रकार ईसीएक्स रजिस्टर में है, लेकिन दुर्भाग्य से mscorlib_ni+0x4102 (78a44102) बहुत उपयोगी नहीं है।

मैं !mln, !mdt और यहां तक ​​कि अवास्तविक !ip2mt, की कोशिश की है लेकिन उनमें से कोई उम्मीद byte या byte[] उत्पादन प्रदर्शित करता है। क्या mscorlib की मूल छवि से प्रकार प्राप्त करने का कोई तरीका है?

+0

सरणी प्रकार वास्तव में ईसीएक्स में पारित किया जा रहा है। हालांकि, नियमित मेटाडेटा टोकन के बजाए, यह 'मेटाडेटा टोकन' के लिए एक हैंडल है। यह जेआईटी द्वारा उत्पन्न होता है। मैं एक हैंडल से मूल मेटाडेटा टोकन में जाने के तरीके से अनजान हूं। इसके बजाय, चूंकि आईएल मौजूद है, इसलिए सरणी प्रकार की पहचान करने के लिए इसे देखना आसान है। – Dono

उत्तर

3

एक तरह से यह आईएल विधि है कि सरणी में बनाया जा रहा है के लिए इसी डंप करने के लिए है क्या करना है।

पहले, !clrstack का उपयोग विधि आप में हैं मिलता है। मेरे मामले में मैं तैयार हूं Main विधि में एक डमी एप्लिकेशन:

0:000> !name2ee ConsoleApplication4!ConsoleApplication4.Program.Main 
Module:  00282eac 
Assembly: ConsoleApplication4.exe 
Token:  0600013c 
MethodDesc: 00283dbc 
Name:  ConsoleApplication4.Program.Main(System.String[]) 
JITTED Code Address: 00320050 
:

0:000> !clrstack 
OS Thread Id: 0x7d0 (0) 
Child SP  IP Call Site 
0016f094 758dc42d [HelperMethodFrame: 0016f094] 
0016f120 003200af ConsoleApplication4.Program.Main(System.String[]) [c:\Users\smt\Documents\Visual Studio 2012\Projects\ConsoleApplication4\Program.cs @ 215] 
0016f2bc 743b3de2 [GCFrame: 0016f2bc] 

अगला उपयोग !name2ee इस पद्धति की विधि की वर्णन (अगले आदेश में यह जरूरत है) प्राप्त करने के लिए

अब, विधि के आईएल डंप:

0:000> !dumpil 00283dbc 
ilAddr = 002d4bc4 
IL_0000: nop 
IL_0001: newobj class [mscorlib]System.Collections.Generic.List`1<?????? ??????n?.::.ctor 
IL_0006: stloc.0 
IL_0007: br.s IL_001e 
IL_0009: nop 
IL_000a: ldc.i4 2147483647 
IL_000f: newarr System.Single 
IL_0014: stloc.1 
IL_0015: ldloc.0 
IL_0016: ldloc.1 
IL_0017: callvirt class [mscorlib]System.Collections.Generic.List`1<?????? ??????N?.::Add 
IL_001c: nop 
IL_001d: nop 
IL_001e: ldc.i4.1 
IL_001f: stloc.2 
IL_0020: br.s IL_0109 

तुलना के लिए, यह सी # में मेरी विधि है:

static void Main(string[] args) 
{ 
    List<float[]> arrays = new List<float[]>(); 
    while (true) 
    { 
     float[] f = new float[Int32.MaxValue]; 
     arrays.Add(f); 
    } 

    Console.ReadKey(); 
} 

आप लाइन IL_000f पर देख सकते हैं कि प्रकार System.Single की एक नई सरणी बनाया जा रहा है ।


मैं इस सड़क से नीचे चला गया क्योंकि मैं वास्तविक देशी विधि को पारित तर्क को समझ नहीं सकता जो सरणी बनाता है। आप बिंदु पर kb चलाते हैं अपवाद फेंक दिया जाता है:

0:000> kb 
ChildEBP RetAddr Args to Child    
WARNING: Stack unwind information not available. Following frames may be wrong. 
0016efa4 74502a42 e0434352 00000001 00000005 KERNELBASE!RaiseException+0x58 
0016f048 745d55ef 00000000 bc1d0b3d 0016f10c clr!RaiseTheExceptionInternalOnly+0x276 
0016f078 7464ae51 bc1d0a7d 0016f150 00000000 clr!UnwindAndContinueRethrowHelperAfterCatch+0x83 
0016f118 003200af 00000000 02202480 00000000 clr!JIT_NewArr1+0x1af 
0016f138 743b3de2 00720198 0016f198 743c3315 0x3200af 
0016f144 743c3315 0016f1dc 0016f188 74502c66 clr!CallDescrWorkerInternal+0x34 
... 

आप देख सकते हैं कि clr!JIT_NewArr1 बुलाया जा रहा है, जो एक आयामी सरणी पैदा करता है। ऐसा करने के लिए, it needs the type and the size। इन तर्कों, ecx और edx में नकल कर रहे हैं, क्रमशः:

0:000> !u 003200AF 
... 
003200a0 b9e2302a73  mov  ecx,offset mscorlib_ni+0x30e2 (732a30e2) 
003200a5 baffffff7f  mov  edx,7FFFFFFFh 
003200aa e89121f5ff  call 00272240 (JitHelp: CORINFO_HELP_NEWARR_1_VC) 
>>> 003200af 8945e8   mov  dword ptr [ebp-18h],eax 
003200b2 8b45e8   mov  eax,dword ptr [ebp-18h] 
003200b5 8945f0   mov  dword ptr [ebp-10h],eax 
... 

आप देख सकते हैं, ecx हो जाता है 732a30e2 है, जो किसी भी तरह System.Single के लिए प्रकार की जानकारी के लिए नक्शे, लेकिन मैं कैसे को समझ नहीं सकता ...

संबंधित मुद्दे