Har*_*Boy 4 debugging symbols windbg
我有一个C#windows服务安装在我想调试的32位Windows Server 2003机器上.
我遇到的问题是日志文件错误消息告诉我以下内容:
System.NullReferenceException: Object reference not set to an instance of an object.
at VideoProcessor.ResetCameraProperties(DataServiceObject dso)
at VideoProcessor.AddServer(DataServiceObject dso)
at VideoProcessor.LoadServers()
at VideoProcessor.Start()
atVideoServerComponent.Connect()
Run Code Online (Sandbox Code Playgroud)
ResetCameraProperties函数的实际代码是:
protected void ResetCameraProperties(DataServiceObject dso)
{
// Find the CameraType.
//Type videoCameraType = TypeManager.Instance["XFire.Common.VideoObjects.VideoServer"];
if (_videoCameraType == null) return;
//Load cameras from the Data Service Layer
string whereClause = "ServerID = ?";
object[] args = new object[] { dso["ObjectID"] };
IDataServiceCollection videoCameraDsoCollection = ClientServerConnection.Instance.FindCollection(_videoCameraType, whereClause, args, null, CollectionOptions.FilterByPartitionResponsibility) as IDataServiceCollection;
if (videoCameraDsoCollection == null || 0 == videoCameraDsoCollection.Count)
return;
videoCameraDsoCollection.LoadContainerOnEnumeration = false;
foreach (DataServiceObject camera in videoCameraDsoCollection)
{
if (!(bool)dso[RecorderKey.Online] && (int)dso[RecorderKey.VideoServerAlarm] == (int)VideoServerComponent.GetVideoServerAlarm("Offline"))
{
// If the server is disconnected, then we know everything should be offline.
camera[CameraKey.VideoCameraAlarm] = VideoServerComponent.GetEnumValueOfType("XFire.Common.VideoObjectDefinitions.VideoCameraAlarm", "Unknown");
camera[CameraKey.Videoloss] = true;
}
else if ((bool)dso[RecorderKey.Online] && (int)dso[RecorderKey.VideoServerAlarm] == (int)VideoServerComponent.GetVideoServerAlarm("Online"))
{
camera[CameraKey.VideoCameraAlarm] = VideoServerComponent.GetEnumValueOfType("XFire.Common.VideoObjectDefinitions.VideoCameraAlarm", "Normal");
camera[CameraKey.Videoloss] = false;
}
// Save the camera.
ServerResult result = ClientServerConnection.Instance.PersistObject(camera, null);
if (result.Fault != null)
{
if (VideoTrace.TraceError) Trace.WriteLine(result.Fault.Message);
}
}
Run Code Online (Sandbox Code Playgroud)
当断点被击中时,我使用F10前进,但我看到的是以下内容:
设置断点:bp 05A0A260 [VideoProcessor.ResetCameraProperties*(XFire.Common.DataServiceLayer.DataServiceObject)]添加待定断点...**0:024> g DriverWindowsService.OnStop服务停止... 断点0命中 eax = 00000001 ebx = 00902870 ecx = 00a1e020 edx = 01066e78 esi = 00affb48 edi = 01066e78 eip = 05a0a260 esp = 0674e68c ebp = 0674e6b0 iopl = 0 nv up ei pl nz na nc cs = 001b ss = 0023 ds = 0023 es = 0023 fs = 003b gs = 0000 efl = 00000202 05a0a260 55 push ebp 0 :024> p eax = 00000001 ebx = 00902870 ecx = 00a1e020 edx = 01066e78 esi = 00affb48 edi = 01066e78 eip = 05a0a261 esp = 0674e688 ebp = 0674e6b0 iopl = 0 nv up ei pl nz na po nc cs = 001b ss = 0023 ds = 0023 es = 0023 fs = 003b gs = 0000 efl = 00000202 05a0a261 8bec mov ebp,esp 0:024> p eax = 00000001 ebx = 00902870 ecx = 00a1e020 edx = 01066e78 esi = 00affb48 edi = 01066e78 eip = 05a0a263 esp = 0674e688 ebp = 0674e688 iopl = 0 nv up ei pl nz na po nc cs = 001b ss = 0023 ds = 0023 es = 0023 fs = 003b gs = 0000 efl = 00000202 05a0a263 57 push edi
这意味着目前不对我(我是一个windbg新手)
在Windbg中我做了View - > Watch,我输入了上面函数内部变量的名称(videoCameraType).但是我收到以下错误:
* ** * 您指定了非限定符号或调试器 * 没有完整的符号信息.不合格的符号 * 默认情况下,分辨率已关闭.请指定一个 * 完全限定的符号模块!符号名称,或启用分辨率* 通过输入".symopt- 100"来表示不合格的符号.注意 * 使用网络符号启用不合格的符号解析 * 符号路径中的服务器共享可能导致调试器 * 似乎挂起了很长一段时间,当一个不正确的 * 键入符号名称或网络符号服务器已关闭. * * 要使某些命令正常工作,请使用符号路径 * 必须指向具有完整类型信息的.pdb文件. * * 某些.pdb文件(例如公共OS符号)不 * 包含所需的信息.联系那个组 * 您提供与这些符号,如果你需要这个命令 * 工作. * ** 参考类型:_videoCameraType * **
如何查看变量,一般看看我的代码中发生了什么?如果有任何帮助,我也有Windows服务的源代码.
谢谢
首先,您的符号文件可能不匹配二进制文件,因为您的异常堆栈跟踪中没有源文件路径和行号.您提到您从Visual Studio调试输出中复制了它们,因此我假设您在Release(没有符号)和Debug中的pdb文件中编译了二进制文件.这不行.您需要做的是更改服务的项目设置,重新编译和部署它(您现在应该在发布输出文件夹中有pdb,dll和exe文件).这应该为您的异常生成更有意义的堆栈跟踪.
现在,第二部分.您需要区分托管环境和本机环境.在windbg中,您正在调试操作系统看到的CLR,因此您不仅要调试C#应用程序,还要调试将ILASM(已编译的C#代码)编译为本机CPU指令然后执行它们的CLR解释器.所以你是一个低于你通常在VS中看到的层(连接了托管调试器).记住这一点你需要深入了解CLR内部并试图弄清楚寄存器中的地址是什么意思,或者使用某种翻译器来完成这项繁重的工作.这就是SOS发挥作用的地方.您在设置断点时已经使用过它.因为您只想知道变量的值,所以您需要先了解CLR在哪个地址为您撒谎.从我看到的_videoCameraType是私人班级成员,不是吗?如果是这样,您可以使用!dso命令从堆栈转储托管对象.您应该看到类似于以下输出的内容:
> !dso
OS Thread Id: 0xad8 (0)
RSP/REG Object Name
000000000068E8F0 00000000025f2bc8 Program+Test
000000000068E8F8 00000000025f2be0 System.String test
000000000068E910 00000000025f2bc8 Program+Test
000000000068E918 00000000025f2bc8 Program+Test
Run Code Online (Sandbox Code Playgroud)
哪里Program+Test将被您的班级名称取代.然后,您可以使用!do命令和Object列中的地址转储对象内容:
> !do 00000000025f2bc8
Name: Program+Test
MethodTable: 000007fe58333a08
EEClass: 000007fe584422b8
Size: 24(0x18) bytes
File: D:\temp\Test.exe
Fields:
MT Field Offset Type VT Attr Value Name
000007feb4dcb318 4000001 8 System.String 0 instance 00000000025f2be0 _testVariable
Run Code Online (Sandbox Code Playgroud)
按名称查找类成员并!do再次使用命令,但使用Value列中的地址(这适用于引用类型).在我们的例子中,它将是:
0:000> !do 00000000025f2be0
Name: System.String
MethodTable: 000007feb4dcb318
EEClass: 000007feb4733720
Size: 34(0x22) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: test
Fields:
MT Field Offset Type VT Attr Value Name
000007feb4dce0c8 40000aa 8 System.Int32 1 instance 4 m_stringLength
000007feb4dcc600 40000ab c System.Char 1 instance 74 m_firstChar
000007feb4dcb318 40000ac 18 System.String 0 shared static Empty
>> Domain:Value 000000000074f960:NotInit <<
Run Code Online (Sandbox Code Playgroud)
如果您需要弄清楚局部变量的值是什么,事情会变得棘手.您可以尝试!CLRStack -a在发布版本中通常不会显示太多内容.然后,您将获得生成的程序集(!U @rip)的分析,以便找出变量的地址落在哪里(注册表,堆栈).搞清楚之后,再次发出!do带有你找到的地址的命令.快乐调试:)