debugging - 如何使用windbg查看c#变量

标签 debugging windbg symbols

我在 32 位 Windows Server 2003 计算机上安装了一个 C# Windows 服务,我希望对其进行调试。

我遇到的问题是日志文件错误消息告诉我以下内容:

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);
            }
     }          
  1. 我已经打开了windbg并执行了File-->Attach to process

  2. 我已使用此处概述的步骤在上述函数中设置断点:https://learn.microsoft.com/en-us/archive/blogs/alejacma/managed-debugging-with-windbg-preparing-the-environment

  3. 当断点被击中时,我使用 F10 前进,但我看到的只是以下内容:

    设置断点:bp 05A0A260 [VideoProcessor.*ResetCameraProperties (XFire.Common.DataServiceLayer.DataServiceObject)] 添加待处理断点... 0:024>克 DriverWindowsService.OnStop 服务正在停止... 断点 0 命中 eax=00000001 ebx=00902870 ecx=00a1e020 edx=01066e78 esi=00affb48 edi=01066e78 eip=05a0a260 esp=0674e68c ebp=0674e6b0 iopl=0 nv 上 ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 05a0a260 55 推 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 上 ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 05a0a261 8bec 移动 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 上 ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 05a0a263 57推送edi

目前这对我来说没什么意义(我是一个 Windbg 新手)

  • 我有 Windows 服务的 pdb 文件(从 Visual Studio 调试输出文件夹获取),并将其复制到目标计算机的文件夹 C:\Symbols 中。

  • 在 winDbg 中,我执行了文件-->符号文件路径并将其设置为我复制的 pdb 文件的位置。我的符号路径如下: C:\symcache;C:\Symbols;srvc:\symcache http://msdl.microsoft.com/download/symbols

  • 在 Windbg 中,我执行了View-->Watch,并输入了上述函数内的变量名称 (videoCameraType)。但我收到以下错误:

    <小时/> <小时/> <小时/>

    *** 您指定了不合格的符号,或者您的调试器 *** *** 没有完整的符号信息。不合格符号*** *** 分辨率默认关闭。请指定 *** *** 完全限定的符号模块!符号名称,或启用解析 *** *** 通过键入“.symopt- 100”来删除不合格的符号。注意 *** *** 使用网络符号启用不合格的符号解析 *** *** 服务器共享符号路径可能会导致调试器*** 当 *** 不正确时,*** 似乎会长时间挂起 *** 输入了符号名称或网络符号服务器已关闭。 ***

    <小时/>

    *** 为了使某些命令正常工作,您的符号路径 *** *** 必须指向具有完整类型信息的 .pdb 文件。 ***

    <小时/>

    *** 某些 .pdb 文件(例如公共(public)操作系统符号)不 *** *** 包含所需的信息。联系 *** 的群组 如果您需要此命令,*** 为您提供了这些符号 *** *** 工作。 ***

    <小时/>

    *** 引用的类型:_videoCameraType ***

    <小时/> <小时/>
  • 我如何查看变量并大致了解我的代码中发生了什么??? 我还有 Windows 服务的源代码(如果有帮助的话)。

    谢谢

    最佳答案

    首先,您的符号文件可能与二进制文件不匹配,因为异常堆栈跟踪中没有源文件路径和行号。您提到您从 Visual Studio 调试输出复制了它们,因此我假设您有在 Release 中编译的二进制文件(没有符号)和来自 Debug 的 pdb 文件。这行不通。您需要做的是change the project settings for your service ,重新编译并部署它(现在发布输出文件夹中应该有 pdb、dll 和 exe 文件)。这应该会为您的异​​常生成更有意义的堆栈跟踪。

    现在,第二部分。您需要区分托管环境和 native 环境。在 Windbg 中,您调试的是操作系统所看到的 CLR,因此您不仅调试 C# 应用程序,还调试 CLR 解释器,该解释器将 ILASM(编译的 C# 代码)编译为 native CPU 指令,然后执行它们。因此,您位于 VS 中通常看到的底层(附加托管调试器)。记住这一点,您需要深入了解 CLR 内部结构并尝试找出寄存器中的地址的含义,或者使用某种转换器来为您完成这项繁重的工作。这就是SOS的地方发挥作用。当你设置断点的时候你就已经使用了它。由于您只对了解变量的值感兴趣,因此您需要首先找出 CLR 为您提供的地址。据我所知, _videoCameraType 是一个私有(private)类成员,不是吗?如果是这样,您可以使用 !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
    

    其中 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
    

    按名称查找类成员,并再次使用 !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  <<
    

    如果您需要弄清楚局部变量的值是什么,事情会变得更加棘手。您可以尝试使用 !CLRStack -a ,它通常在发布版本中不会显示太多内容。然后,您需要分析生成的程序集 (!U @rip),以便找出变量的地址(注册表、堆栈)。弄清楚这一点后,使用您找到的地址再次发出 !do 命令。祝调试愉快:)

    关于debugging - 如何使用windbg查看c#变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17726879/

    相关文章:

    c++ - 简单的双端队列程序表现出奇怪的行为

    c - malloc() 每次都会崩溃 || Windbg 与 nt!DbgLoadImageSymbols 发生冲突

    r - 如何在R中的plotmath中写远小于符号(<<)?

    c++ - 据说调试符号不会为文档加载,即使它们是为 dll 加载的

    visual-studio-2010 - 指定要从 VS2010 调试 session 中排除的多个符号

    ruby - 如何调试 ruby​​ 代码?

    使用 Pdb 进行 Python 调试

    visual-studio-2010 - 如何在 VS2010 Watch 窗口中重新排列(或排序)变量?

    debugging - ADPlus/CDB 的不一致行为 - 'g' 中没有可运行的调试器错误

    windows - WinDbg:设置断点时无法解决 xyz!abc::func 处的错误