2011-06-07 33 views
8

我有一個.Net應用程序轉儲,它捕獲到一個異常,我使用windbg進行分析,並對其中一個方法的String參數的值感興趣。我已經隔離了String對象。我的WinDbg的工作是:在windbg中調試.Net字符串值

0:000> .loadby sos mscorwks 
0:000> !dso 
OS Thread Id: 0x16f0 (0) 
RSP/REG   Object   Name 
00000000001fe908 000000000f011440 System.AppDomainSetup 
00000000001fe918 000000000f0335f8 System.ArgumentException 
00000000001fe920 000000000f011b60 System.String 

0:000> !do 000000000f011b60 

Name: System.String 
MethodTable: 000007feef477a80 
EEClass: 000007feef07e530 
Size: 538(0x21a) bytes 
(C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll) 
String: C:\Windows\Installer\MSI2D87.tmp 
Fields: 
       MT Field Offset     Type VT  Attr   Value Name 
000007feef47ecf0 4000096  8   System.Int32 1 instance    257 m_arrayLength 
000007feef47ecf0 4000097  c   System.Int32 1 instance    179 m_stringLength 
000007feef4794c8 4000098  10   System.Char 1 instance    43 m_firstChar 
000007feef477a80 4000099  20  System.String 0 shared   static Empty 
           >> Domain:Value 00000000029d02d0:000000000f011308 << 
000007feef479378 400009a  28  System.Char[] 0 shared   static WhitespaceChars 
           >> Domain:Value 00000000029d02d0:000000000f0121f8 << 

的m_stringLength成員變量表示字符串是179個字符長,但是它檢查似乎只有32個字符長的字符串。查看此字符串的內存似乎是NULL終止。 NULL終止字符後面有更多字符。這可能是重複使用的內存或字符串損壞,但路徑顯示正確。 拋出的異常是'路徑中的非法字符',但在這條路徑中沒有非法字符。 所以對於此異常調用堆棧是:

0:000> !CLRStack 
OS Thread Id: 0xbac (0) 
Child-SP   RetAddr   Call Site 
000000000021e9a0 000007feeea64dec System.IO.Path.CheckInvalidPathChars(System.String) 
000000000021e9e0 000007feee9c0e66 System.IO.Path.NormalizePathFast(System.String, Boolean) 
000000000021eaa0 000007feee9badf8 System.AppDomainSetup.NormalizePath(System.String, Boolean) 
000000000021eb10 000007feeea630ad System.AppDomainSetup.SetupDefaultApplicationBase(System.String) 
000000000021eb70 000007feee9bb27b System.AppDomain.SetupFusionStore(System.AppDomainSetup) 
000000000021ebc0 000007feef87d4a2 System.AppDomain.SetupDomain(Boolean, System.String, System.String) 

是否System.IO.Path.CheckInvalidPathChars方法過程中使用的m_stringLength發現長度字符串,或者它考慮到字符串本身的NULL終止? 我也接受這樣一個事實,即如果你能發現我沒有的東西,還有其他的錯誤。

回答

1

這裏是System.IO.Path.CheckInvalidPathChars做(至少在.NET 2.0):

for (int i = 0; i < path.Length; i++) 
{ 
    int num2 = path[i]; 
    if (((num2 == 0x22) || (num2 == 60)) || (((num2 == 0x3e) || (num2 == 0x7c)) || (num2 < 0x20))) 
    { 
     throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars")); 
    } 
} 

注意string.length減的有趣的部分,如何字符串實際上暴露了,它的長度財產,丟失:

public int Length { [MethodImpl(MethodImplOptions.InternalCall)] get; } 

我會嘗試,如果可能的模擬問題,通過檢索準確的字符串(最多存儲在m_stringLength長度),並試圖重現該問題。

+0

這是我懷疑 - 感謝確認。 – MrBry 2011-06-08 11:24:40

5

我會將實際的字符串從內存中轉儲到文件中以檢查內容,而不是僅僅查看windbg中的輸出。

這是我寫的一個Windbg腳本,用於將字符串轉儲到文件。

$$ Dumps the managed strings to a file 
$$ Platform x86 
$$ Usage $$>a<"c:\temp\dumpstringtofolder.txt" 6544f9ac 5000 c:\temp\stringtest 
$$ First argument is the string method table pointer 
$$ Second argument is the Min size of the string that needs to be used filter the strings 
$$ Third is the path of the file 
.foreach ($string {!dumpheap -short -mt ${$arg1} -min ${$arg2}}) 
{ 

    $$ MT  Field  Offset    Type VT  Attr Value Name 
    $$ 65452978 40000ed  4   System.Int32 1 instance 71117 m_stringLength 
    $$ 65451dc8 40000ee  8   System.Char 1 instance  3c m_firstChar 
    $$ 6544f9ac 40000ef  8  System.String 0 shared static Empty 

    $$ start of string is stored in the 8th offset, which can be inferred from above 
    $$ Size of the string which is stored in the 4th offset 
    [email protected]$t0= poi(${$string}+4)*2 
    .writemem ${$arg3}${$string}.txt ${$string}+8 ${$string}[email protected]$t0 
} 

的整體思路是使用.writemem命令將內容記錄到文件中。

轉儲的內容將是Unicode格式,並查看其內容使用類似這樣

Console.WriteLine(ASCIIEncoding.Unicode.GetString(File.ReadAllBytes(@"c:\temp\stringtest03575270.txt")));

HTH