我有一个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()
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);
}
}
-
我打开了windbg并执行了File - > Attach to process
-
我使用此处列出的步骤在上面的函数中设置了断点:http://blogs.msdn.com/b/alejacma/archive/2009/07/13/managed-debugging-with-windbg-preparing-the-environment.aspx
-
当断点被击中时,我使用F10前进,但我看到的是以下内容:
设置断点:bp 05A0A260 [VideoProcessor . *ResetCameraProperties (XFire.Common.DataServiceLayer.DataServiceObject)] Adding pending breakpoints... 0:024> g DriverWindowsService.OnStop服务停止... Breakpoint 0 hit 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 po 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 n cs = 001b ss = 0023 ds = 0023 es = 0023 fs = 003b gs = 0000 efl = 00000202 05a0a263 57推edi
这意味着目前不对我(我是一个windbg新手)
-
我有Windows服务的pdb文件(我从Visual Studio Debug Output文件夹获得)并将其复制到我的目标机器 C:\Symbols 文件夹中 .
-
在winDbg中我做了 File-->Symbol FIle path 并将其设置为我复制过的这个pdb文件的位置 . 我的符号路径如下: C:\symcache;C:\Symbols;srvc:\symcachehttp://msdl.microsoft.com/download/symbols
-
在Windbg中我做了 View-->Watch 并输入了上面函数内的变量名( videoCameraType ) . 但是我收到以下错误:
***** ** ***** 您指定了非限定符号,或者您的调试器 **** ***** 没有完整的符号信息 . 默认情况下,非限定符号 ***** 分辨率处于关闭状态 . 请指定 **** ***** 完全限定符号模块!symbolname,或通过键入".symopt- 100"启用非限定符号的解决方案 ***** . 请注意,在符号路径中使用网络符号 ***** 服务器共享启用不合格的符号解析时,可能会导致调试器在输入错误的 ***** 符号名称或网络符号服务器关闭时长时间挂起.2903075_ ***** . **** ***** ***** 要使某些命令正常工作,您的符号路径 **** ***** 必须指向具有完整类型信息的.pdb文件 . ***** **** ***** 某些.pdb文件(例如公共OS符号)不包含 ***** 所需的信息 . 如果您需要此命令 ***** work,请联系 **** ***** 为您提供这些符号的组 . **** ***** *** *** 引用的类型:_videoCameraType ***** **
如何查看变量,一般看看我的代码中发生了什么?如果有任何帮助,我也有Windows服务的源代码 .
谢谢
2 回答
首先,您的符号文件可能不匹配二进制文件,因为您的异常堆栈跟踪中没有源文件路径和行号 . 您提到您从Visual Studio调试输出中复制了它们,因此我假设您在Release(没有符号)和Debug中的pdb文件中编译了二进制文件 . 这不行 . 您需要做的是change the project settings for your service,重新编译并部署它(您现在应该在release output文件夹中有pdb,dll和exe文件) . 这应该为您的异常生成更有意义的堆栈跟踪 .
现在,第二部分 . 您需要区分托管环境和本机环境 . 在windbg中,您正在调试操作系统看到的CLR,因此您不仅要调试C#应用程序,还要调试将ILASM(已编译的C#代码)编译为本机CPU指令然后执行它们的CLR解释器 . 所以你是一个低于你通常在VS中看到的层(连接了托管调试器) . 记住这一点你需要深入了解CLR内部并试图弄清楚寄存器中的地址是什么意思,或者使用某种翻译器来完成这项繁重的工作 . 这就是SOS发挥作用 . 您在设置断点时已经使用过它 . 因为您只想知道变量的值,所以您需要先了解CLR在哪个地址为您撒谎 . 从我看到
_videoCameraType
是私人 class 成员,不是吗?如果是这样,您可以使用!dso
命令从堆栈转储托管对象 . 您应该看到类似于以下输出的内容:其中
Program+Test
将被您的 class 名称替换 . 然后,您可以使用!do
命令和Object
列中的地址转储对象内容:按名称查找类成员并再次使用
!do
命令,但使用Value
列中的地址(这适用于引用类型) . 在我们的例子中,它将是:如果您需要弄清楚局部变量的值是什么,事情会变得棘手 . 您可以尝试使用
!CLRStack -a
,这通常在发布版本中没有显示多少 . 然后,您将分析生成的程序集(!U @rip
),以便找出变量的地址落在哪里(注册表,堆栈) . 搞清楚之后,再次发出带有您找到的地址的!do
命令 . 快乐调试:)添加到此主题,因为它显示在Google搜索中:
以下对我有用:
(如果应用程序使用.net 4,请使用.loadby sos clr加载SOS调试器扩展)
一旦你在正确的线程上,首先使用!clrstack -p转储堆栈以及局部变量的地址 .
现在使用感兴趣的局部变量的地址来使用!do转储它 .
然后使用您获得的输出中的地址 - 您可以再次使用!do(使用此处的Value字段作为特定成员的地址) . 你可以继续,直到你能够看到你想要的 Value .
(您也可以使用这种方法来转储从堆栈中获取的“this”指针的成员 . 这可能会根据您的需要找到一些感兴趣的变量)
见http://blogs.msdn.com/b/alejacma/archive/2009/08/11/managed-debugging-with-windbg-thread-stacks-part-1.aspx
调试很刺激!玩得开心!