【问题标题】:In Visual Studio, can I set conditional breakpoints that can peek variables from another scope?在 Visual Studio 中,我可以设置可以从另一个范围窥视变量的条件断点吗?
【发布时间】:2021-07-19 14:39:45
【问题描述】:

看这段代码:

void F1() {
    for (int i = 0; i < 100; i ++)
        F2();
}

void F2() {
    for (int i = 0; i < 100; i ++)
        F3();
}

void F3() {
    int a = 0; // break point here
    for (int i = 0; i < 100; i ++)
        a ++;
}

我想在F3() 中的int a = 0; 行设置一个断点,但我只想在F1() 中的i==70F2() 中的i==80 时暂停。

这意味着当我在F3() 的范围内时,我必须查看F2()F1() 的局部变量。但在实际代码中,这两个变量并不意味着要传递下去。

这样做的正确方法是什么?

【问题讨论】:

  • 相关,不一定重复:stackoverflow.com/a/4251470/1132334(object id方式,object ids在断点的条件框内有效)
  • 在这种情况下,我通常会创建一个全局变量进行调试。
  • 你看不到范围外的变量,因为它们不存在于另一个范围内。
  • @0___________ 在程序内没有,但我不太确定 MSVC 调试器,因为它支持所谓的ObjectID references

标签: c# visual-studio debugging


【解决方案1】:

如果可以更改代码,我可以想象的干扰较少的代码如下 - 不使用 @Maaz 的点击计数的技巧。

它基于使用当前线程来“存储”值。

void F1() {
    for (int i = 0; i < 100; i ++)
    {
        CallContext<Int32>.SetData("i-first", i);
        F2();
    }
}

void F2() {
    for (int i = 0; i < 100; i ++)
    {
        CallContext<Int32>.SetData("i-second", i);
        F3();
    }
}

void F3() {
    int a = 0; // break point here
    for (int i = 0; i < 100; i ++)
        a ++;
}

//Helper class for .Net Core.
//For .Net Framework you can use CallContext.LogicalSetData, CallContext.LogicalGetData
public static class CallContext<T>
{
    static ConcurrentDictionary<string, AsyncLocal<T>> state = 
         new ConcurrentDictionary<string, AsyncLocal<T>>();

    public static void SetData(string name, T data) =>
            state.GetOrAdd(name, _ => new AsyncLocal<T>()).Value = data;

    public static T GetData(string name) =>
            state.TryGetValue(name, out AsyncLocal<T> data) ? data.Value : default(T);
}

断点的条件表达式为:

CallContext<Int32>.GetData("i-first") == 70 && CallContext<Int32>.GetData("i-second") == 80

【讨论】:

  • 这看起来不错。添加一些代码对我来说是可以的。
【解决方案2】:

也许您可以添加一个计数器来跟踪函数 F3() 被调用的次数。

//track F3() call of times
private int times = 0;
void F3() {
    int a = 0; // break point if times == 70 || times == 80
    for (int i = 0; i < 100; i ++)
        a ++;    
    //add 1 call of times
    times++;
}

【讨论】:

  • 只有代码的答案很酷。但也许你可以添加细节和解释。比如:“也许你想添加一个计数器来跟踪times的数量,调用函数Foo()。这样你就可以用它来跟踪......等等的执行次数"
  • 这确实是一个解决方案。但有时我们需要的不是计数。例如,我在F1() 中需要的条件可能是some_array[i] == "Tom"
【解决方案3】:

您可以设置一个条件断点来进行命中测试。将其设置为达到7081 的值,它应该可以工作。

F2() 被称为 70 次,对于每个 70 次,F3() 被称为 100 次。因此,对于第 71 个循环,即 F1() 的 i == 70,和第 81 个子循环,即 F2() 的 i == 8070*100 + 81 的命中测试应该可以工作。

【讨论】:

  • 不是每次都重置吗?存在范围问题。
  • 是的,a 会的。但是,正如问题所建议的那样,要停在确切的行上,这就是我的想法。
【解决方案4】:

是的,请按照以下步骤操作

  1. 在要调试的行上设置断点
  2. 右键单击断点
  3. 选择“条件”,这将提示您弹出窗口
  4. 写条件
  5. 关闭并调试。

【讨论】:

  • 这如何解决超出范围的变量问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-05
  • 2014-07-11
  • 1970-01-01
  • 1970-01-01
  • 2015-07-20
  • 2011-03-15
相关资源
最近更新 更多