8

例外をキャプチャした .Net アプリケーション ダンプがあります。windbg を使用して分析しており、メソッドの 1 つで String パラメータの値に関心があります。String オブジェクトを分離しました。私のwindbgの作業は次のとおりです。

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 終端を考慮しますか? また、私が見つけられなかった何かを見つけることができれば、他に何か問題があるという事実にもオープンです。

4

2 に答える 2

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
  r@$t0=  poi(${$string}+4)*2
  .writemem ${$arg3}${$string}.txt ${$string}+8 ${$string}+8+@$t0
}

全体的なアイデアは、.writememコマンドを使用してコンテンツをファイルにダンプすることです。

ダンプされたコンテンツは Unicode 形式になり、そのコンテンツを表示するには、次のようなものを使用します

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

HTH

于 2011-06-07T13:28:11.513 に答える
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 の興味深い部分、つまり string が実際に length プロパティを公開する方法が欠落していることに注意してください。

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

可能であれば、正確な文字列 (m_stringLength に格納されている長さまで) を取得し、問題を再現することによって、問題をシミュレートしようとします。

于 2011-06-07T11:06:27.773 に答える