2011-03-18 28 views
11

我正在使用帶SoS擴展名的WinDbg調試來自生產服務器的hangdump。WinDbg和SoS,如何打印/轉儲大字符串?

在其中一個堆棧中有一個字符串參數,我需要知道它的值。但是,它是一個相當大的字符串,並且當我使用DumpObj時,WinDbg將不打印它。這是DumpObj的輸出:

0:036> !do 00000001b30d8668 
Name: System.String 
MethodTable: 0000064278436728 
EEClass: 000006427803e520 
Size: 5125300(0x4e34b4) bytes 
(C:\WINDOWS\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll) 
String: <String is invalid or too large to print> 

Fields: 
       MT Field Offset     Type VT  Attr   Value Name 
000006427843d998 4000096  8   System.Int32 1 instance   2562638 m_arrayLength 
000006427843d998 4000097  c   System.Int32 1 instance   2562637 m_stringLength 
0000064278438170 4000098  10   System.Char 1 instance    3c m_firstChar 
0000064278436728 4000099  20  System.String 0 shared   static Empty 
           >> Domain:Value 0000000000163260:000000007fff0370 00000000001a6760:000000007fff0370 << 
0000064278438020 400009a  28  System.Char[] 0 shared   static WhitespaceChars 
           >> Domain:Value 0000000000163260:000000007fff0b60 00000000001a6760:000000007fff89f0 << 

如何獲取此字符串實例的值?最好轉儲到文件。

回答

7

在轉儲2562638個字符的文本之前,我會三思而後行,但如果您真的想,文本會存儲在字符串實例的字段之後,因此您可以執行du <address+offset> <end address>轉儲字符串的實際文本。輸出會是這個樣子:

00000000`132ab050 "this is an extremely long string" 
00000000`132ab090 " of text, so don't even bother t" 
00000000`132ab0d0 "o try to dump it to the screen -" 

通過登錄會話輸出到文件,您可以輕鬆地捕獲輸出,做任何後期處理需要。

+0

如果字符串非常長,由於限制,起始地址/結束地址語法將不起作用。你需要使用du

L? <以字節爲單位的長度>。 對於真正長的字符串,這實際上會花費太長時間,WinDbg沒有再響應。 – 2013-12-11 12:10:39

+0

我在日誌中收到與命令窗口中相同的消息:<字符串無效或太大而無法打印> – 2015-04-17 20:35:40

+0

我不明白。你會輸入什麼命令? – 2016-03-05 12:16:31

13

這是我寫的一個腳本,用於將字符串轉儲到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 
} 

,這是它如何被使用$$>a<」c:\temp\dumpstringtofolder.txt」 6544f9ac 5000 c:\temp\stringtest

轉儲的內容將是Unicode格式,並查看其內容使用類似這樣Console.WriteLine(ASCIIEncoding.Unicode.GetString(File.ReadAllBytes(@"c:\temp\stringtest03575270.txt")));

HTH

+0

我無法讓腳本爲我工作,但.writemem函數足夠簡單,基於您的示例,我可以讓它自己工作。 – 2013-04-15 17:25:46

+0

@AndrewArnott我能夠使用這個腳本轉儲字符串,我經常使用它。你遇到了什麼問題?你在x86/x64中使用它嗎? – Naveen 2013-04-16 18:23:23

+1

不知道我們是否可以依賴!Name2EE的輸出,但是這可以用來自動獲取方法表指針(r @ $ t1),所以我們可以去除參數1。 .foreach/pS 7/ps 4 (方法表{!Name2EE mscorlib.dll System.String}){r @ $ t1 = $ {methodtable}} – 2013-12-11 11:43:47

1

如果你是匆匆忙忙,在WinDbg中啓用日誌後運行!在日誌文件中,您將獲得整個字符串。

在WinDbg菜單中,進入編輯 - >打開/關閉日誌文件,設置日誌文件路徑。

+0

我只是在日誌文件中得到相同的截斷字符串。只是FYI ... – Jace 2014-09-23 18:04:07

+1

我在日誌中收到與命令窗口中相同的消息:<字符串無效或太大以至於無法打印> – 2015-04-17 20:33:32