MrB*_*Bry 8 .net debugging windbg postmortem-debugging
我有一个.Net应用程序转储捕获异常,我正在使用windbg进行分析,并对其中一个方法的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 <<
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
System.IO.Path.CheckInvalidPathChars方法是否使用m_stringLength中找到的长度处理字符串,还是考虑到字符串本身中的NULL终止?如果你能发现我没有发现的东西,我也会接受这样的事实.
我会将内存中的实际字符串转储到文件中以检查内容,而不是仅仅查看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
}
Run Code Online (Sandbox Code Playgroud)
整个想法是使用该.writemem
命令将内容转储到文件中.
转储的内容将采用Unicode格式,并使用类似的内容查看其内容
Console.WriteLine(ASCIIEncoding.Unicode.GetString(File.ReadAllBytes(@"c:\temp\stringtest03575270.txt")));
HTH
这是 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"));
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,string.Length 中有趣的部分(即 string 如何实际公开其 length 属性)缺失了:
public int Length { [MethodImpl(MethodImplOptions.InternalCall)] get; }
Run Code Online (Sandbox Code Playgroud)
如果可能的话,我会尝试通过检索确切的字符串(最多存储在 m_stringLength 中的长度)并尝试重现该问题来模拟该问题。
归档时间: |
|
查看次数: |
3076 次 |
最近记录: |