【问题标题】:Out Of Context Variables In Visual Studio 2010 DebuggerVisual Studio 2010 调试器中的上下文变量
【发布时间】:2012-01-30 03:39:30
【问题描述】:

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

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

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

有什么想法吗?

编辑:

添加一些附加信息:

问题是可重复的。完全相同的变量要么工作要么不工作,即使在完全关闭并重新启动 Visual Studio 之后也是如此。这让我相信实际上存在系统性问题,而不仅仅是内存损坏或其他问题。

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

另一个编辑:

我(部分地)收回我所说的关于 try-catch 可疑的说法 - 在这部分代码中,调试器似乎表现出这种奇怪的将任何封闭块的内容脱离上下文的情况。例如,如果我直接在屏幕截图中的 foreach 语句内设置断点,我可以在每次迭代中看到“端口”变量值,但在 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
  • 检查您的项目属性:您确定您的调试配置没有更改为“优化代码”吗?
  • @phoog 感谢您的建议。我刚刚检查了项目属性,没有选中“优化代码”。
  • SP1 安装了吗?贴出实际的重现代码,截图不行。
  • @Hans 我正在运行 SP1(刚刚检查了关于窗口以确保 - 实际版本是 10.0.30319.1)。如果这可能有帮助,也在 Windows 7 64 上。不幸的是,我无法发布整个存储库——它既是公司专有的,又非常复杂(即,它不是为其他人设置的,现在只能进行构建)。不过,我使用了几个非常复杂的解决方案,这是我第一次看到这个问题。

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


【解决方案1】:

所以事实证明这与 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 或更高版本(鉴于错误的严重性,这可能应该是实际版本)。

感谢大家的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多