Visual Studio 2010调试器中的上下文变量

时间:2011-12-29 19:41:07

标签: c# visual-studio visual-studio-2010 debugging

对于面向.NET 4.0的C#控制台应用程序,Visual Studio 2010调试器中的局部变量脱离了上下文,我遇到了一个非常奇怪的问题。我在SO上搜索过其他类似的问题,但有些问题有相同的症状,似乎没有一个直接适用于这个问题(它们似乎都有其他根本原因)。

问题在于,对于某些变量(但不是全部),我没有得到带有值的工具提示,它们没有出现在Locals窗口中,我得到“当前上下文中不存在名称'xyz' “如果我将它们添加到Watch窗口。它似乎影响了一些变量而不影响其他变量,我无法弄清楚一个模式(它似乎不是基于成员与本地,类与结构或任何其他区别)。我已经重新启动了我的计算机和Visual Studio,验证了我是一个干净的Debug版本,确保调试框架是正确的,确保刷新监视屏幕中的变量,并尝试各种法术和咒语。

我在下面添加了一个屏幕截图(http://i.stack.imgur.com/JTFBT.png处的更大版本)。

enter image description here

有什么想法吗?

编辑:

添加一些其他信息:

问题是可重复的。即使在完全关闭并重新启动Visual Studio之后,完全相同的变量也可以工作或不起作用。这让我相信实际上存在一些系统性的错误,而不仅仅是内存损坏等等。

我还发现它似乎与try-catch块有关。如果我将断点放在try语句之外,我可以正常看到任何范围内的变量。一旦执行点进入try语句,try块之外的所有变量都将变得不可访问,我只能访问try语句中的变量。这几乎就像调试器将try块视为一个单独的方法一样(尽管你可以看到代码/编译器仍然可以访问范围内的变量)。有没有人见过这种行为?

另一个编辑:

我(部分)收回了我所说的关于try-catch被怀疑的内容 - 看起来在代码的这一部分中,调试器展示了这个奇怪的东西在任何封闭块的上下文之外。例如,如果我在屏幕截图中的foreach语句中直接设置断点,我可以在每次迭代时看到“port”变量值,但是在foreach语句之外没有变量(一旦我进入foreach块就会消失) 。然后,只要您进入try块,“port”变量就会突然消失。这真的很奇怪。

另外,根据要求,整个方法的代码如下。

private void ConfigureAnnouncerSockets(XDocument configDocument)
{
    XElement socketsElement = configDocument.XPathSelectElement("/Configuration/Network/AnnouncerSockets");
    bool useDefault = true;
    if (socketsElement != null)
    {
        //Use the default announcers? (they will be added at the end)
        XAttribute defaultAttribute = socketsElement.Attribute("useDefault");
        if (defaultAttribute != null)
        {
            useDefault = Convert.ToBoolean(defaultAttribute);
        }

        //Get the default frequency
        int defaultFrequency = Announcer.DefaultFrequency;
        XAttribute frequencyAttribute = socketsElement.Attribute("frequency");
        if (frequencyAttribute != null)
        {
            defaultFrequency = Convert.ToInt32(frequencyAttribute.Value);
        }

        //Get all sockets
        foreach (XElement socketElement in socketsElement.XPathSelectElements("./Socket"))
        {
            //Get the address
            IPAddress address = IPAddress.Broadcast;
            string addressAttribute = (string)socketElement.Attribute("address");
            if(!GetAddress(addressAttribute, ref address, true))
            {
                Intelliplex.Log.Warn("Invalid announcer socket address: " + addressAttribute);
                continue;
            }

            //Get the local address
            IPAddress localAddress = null;
            string localAddressAttribute = (string)socketElement.Attribute("localAddress");
            if(!GetAddress(localAddressAttribute, ref localAddress, false))
            {
                Intelliplex.Log.Warn("Invalid announcer socket local address: " + localAddressAttribute);
                continue;
            }

            //Get the port(s)
            List<int> ports = new List<int>();
            string[] ranges = ((string)socketElement.Attribute("port")).Split(new[] { ',' });
            foreach (string range in ranges)
            {
                string[] portPair = range.Split(new[] { '-' });
                int firstPort = Convert.ToInt32(portPair[0]);
                int lastPort = portPair.Length > 1 ? Convert.ToInt32(portPair[1]) : firstPort;
                do
                {
                    ports.Add(firstPort);
                } while (++firstPort <= lastPort);
            }

            //Get the local port
            int localPort = socketElement.Attribute("localPort") != null
                ? Convert.ToInt32((string)socketElement.Attribute("localPort")) : 0;

            //Get the frequency
            int frequency = socketElement.Attribute("frequency") != null
                ? Convert.ToInt32((string)socketElement.Attribute("frequency")) : defaultFrequency;

            //Create the socket(s) and add it/them to the manager
            foreach (int port in ports)
            {
                try
                {
                    IPEndPoint endPoint = new IPEndPoint(address, port);
                    IPEndPoint localEndPoint = localAddress == null
                        ? new IPEndPoint(IPAddress.Any, 0) : new IPEndPoint(localAddress, localPort);
                    Announcer socket = new Announcer(frequency, endPoint, localEndPoint);
                    AnnouncerSockets.Add(socket);
                }
                catch (Exception ex)
                {
                    Intelliplex.Log.Warn("Could not add announcer socket: " + ex.Message);
                }
            }
        }
    }

    //Add default announcement sockets?
    if (useDefault)
    {
        ConfigureDefaultAnnouncerSockets();
    }
}

1 个答案:

答案 0 :(得分:9)

事实证明这与PostSharp中的错误有关。我一直在使用PostSharp,但从我的代码中删除了所有方面,并确保没有应用。我还用Reflector验证了方法在装配中是完整的。但是,它似乎只是引用PostSharp触发某种导致此问题的调试符号的操作。可以在这里找到(小)更多信息:

http://www.sharpcrafters.com/forum/Topic5794-21-1.aspx#bm7927

此外,在最新的PostSharp修补程序的发行说明中,修补程序2.1.5.6中的一个已修复问题是“调试符号:隐式迭代器中丢失的局部变量符号。”

当我安装最新最好的PostSharp时,问题消失了,宇宙恢复正常。希望这个问题/答案将帮助其他任何使用PostSharp的人在下一次官方PostSharp发布之前偶然发现这种奇怪的行为。确保你使用的是修补程序2.1.5.6或更高版本(鉴于错误的严重性,这可能应该是一个实际版本)。

感谢所有人的帮助。