zoukankan      html  css  js  c++  java
  • Visual Studio调试托管代码

    “输出”窗口中的诊断消息

    可以使用 Debug 类或 Trace 类(属于 System.Diagnostics 类库)将运行时消息写到“输出”窗口。 如果只在程序的调试版本中输出,则使用 Debug 类。 如果要同时在调试版本和发布版本中输出,则使用 Trace 类。

    输出方法

    Trace 和 Debug 类提供下列输出方法:

    • 在不中断执行情况下输出信息的各种 Write 方法。 这些方法取代了在 Visual Basic 早期版本中使用的 Debug.Print 方法。

    • Debug.Assert 和 Trace.Assert 方法,如果指定的条件失败,这些方法将中断执行并输出信息。 默认情况下,Assert 方法显示对话框中的信息。 有关更多信息,请参见托管代码中的断言。

    • Debug.Fail 和 Trace.Fail 方法,它们总是中断执行并输出信息。 默认情况下,Fail 方法在对话框中显示信息。

    除了应用程序的程序输出外,**“输出”**窗口还可以显示下列信息:

    • 调试器已经加载或卸载的模块。

    • 引发的异常。

    • 退出的进程。

    • 退出的线程。

    托管代码中的断言

    断言(或 Assert 语句)测试您作为 Assert 语句的参数指定的条件。 如果此条件计算为 true,不发生操作。 如果此条件计算为 false,则断言失败。 如果正在调试版本中运行,则程序进入中断模式。

    在 Visual Basic 和 Visual C# 中,可以使用方法调用,可以从 System.Diagnostics 命名空间下的 Debug 或 Trace 调用 Assert 方法。 在您的程序的发布版本中不包含 Debug 类方法,因此它们不增大或减小发布代码的速度。

    C++ 不支持 Debug 类方法。 使用带有条件编译的 Trace 类(如 #ifdef DEBUG...)可获得同样的效果。 #endif.

    Debug.Assert 方法

    可随意使用 Debug.Assert 方法测试条件,如果代码正确,该条件应保持为真。 例如,假设已编写一个整数除法函数。 根据数学规则,除数永远不能为零。 可以使用断言测试该条件:

    [C#]

     
    int IntegerDivide ( int dividend , int divisor )
        { Debug.Assert ( divisor != 0 );
            return ( dividend / divisor ); }
    

    当在调试器下运行该代码时,将计算断言语句,但是在发行版本中,将不进行该比较,因此没有额外的系统开销。

    以下是另一个示例。 您有一个实现支票活期存款帐户的类,如下所示:

    [C#]

     
    float balance = savingsAccount.Balance;
    Debug.Assert ( amount <= balance );
    savingsAccount.Withdraw ( amount );
    

    在从该帐户中提取钱之前,您想要确保帐户的余额大于准备取出的金额。 可以编写检查余额的断言:

    [C#]

     
    float balance = savingsAccount.Balance;
    Trace.Assert ( amount <= balance );
    savingsAccount.Withdraw ( amount );
    

    注意,当创建代码的发行版本时,对 Debug.Assert 方法的调用将消失。 这意味着在发行版本中检查余额的调用将消失。 若要解决此问题,您应使用不会在发行版本中消失的 Trace.Assert 替换 Debug.Assert:

    与对 Debug.Assert 的调用不同,对 Trace.Assert 的调用会增加发行版本的系统开销。

    Debug.Assert 的副作用

    使用 Debug.Assert 时,确保 Assert 中的任何代码不会更改程序的结果(如果移除 Assert)。 否则,可能会意外地引入一个只在程序的发行版本中出现的 bug。 对于包含函数或过程调用的断言要特别小心,如下面的示例:

    [C#]

     
    // unsafe code
    Debug.Assert (meas(i) != 0 );
    

    乍一看,使用 Debug.Assert 似乎很安全,但是假设每次调用函数 meas 时该函数都会更新计数器。 当生成发行版本时,由于消除了对 meas 的调用,因此计数器将得不到更新。 这是一个带“副作用”的函数的示例。 消除对具有副作用的函数的调用会导致一个只出现在发行版本中的 bug。 为避免这样的问题,请不要将函数调用放在 Debug.Assert 语句中。 改用临时变量:

    [C#]

     
    temp = meas( i );
    Debug.Assert ( temp != 0 );
    

    即使在使用 Trace.Assert 时,也需要避免将函数调用放置到 Assert 语句中。 这样的调用应是安全的,因为在发行版本中没有消除 Trace.Assert 语句。 但是,如果习惯上避免这样的结构,则使用 Debug.Assert 时犯错误的可能性很小。

    Trace 和 Debug 的要求

    如果使用 Visual Studio 向导创建项目,则默认情况下,“发布”配置和“调试”配置中都定义了 TRACE 符号。 默认情况下,只在调试版本中定义 DEBUG 符号。

    否则,若要使 Trace 方法工作,程序必须在源文件的顶部放置以下代码之一:

    • Visual Basic 中的 #Const TRACE = True

    • Visual C# 和 C++ 中的 #define TRACE

    或者,程序必须是用 TRACE 选项生成的:

    • Visual Basic 中的 /d:TRACE=True

    • Visual C# 和 C++ 中的 /d:TRACE

    如果需要在 C# 或 Visual Basic 发行版本中使用 DEBUG 方法,必须在“Release”配置中定义 DEBUG 符号。

    C++ 不支持 Debug 类方法。 使用带有条件编译的 Trace 类(如 #ifdef DEBUG...)可获得同样的效果。 #endif. 可以在**“<项目> 属性页”**对话框中定义这些符号。 有关更多信息,请参见为 Visual Basic 调试配置更改项目设置或更改 C 或 C++ 调试配置的项目设置。

    Assert 参数

    Trace.Assert 和 Debug.Assert 最多有三个参数。 第一个参数是强制的,它是想要检查的条件。 如果仅用一个参数来调用 Trace.Assert(Boolean) 或 Debug.Assert(Boolean),Assert 方法将检查条件,并且如果结果是 false,则向**“输出”**窗口输出调用堆栈的内容。 下面的示例显示 Trace.Assert(Boolean) 和 Debug.Assert(Boolean):

    [C#]

     
    Debug.Assert ( stacksize > 0 );
    Trace.Assert ( stacksize > 0 ); 
    

    第二个和第三个参数(如果有)必须是字符串。 如果调用带有两个或三个参数的 Trace.Assert 或 Debug.Assert,则第一个参数是一个条件。 该方法检查此条件,如果结果为 false,则输出第二个和第三个字符串。 下面的示例演示 Debug.Assert(Boolean, String) 和 Trace.Assert(Boolean, String) 使用两个参数的情况:

    [C#]

     
    Debug.Assert ( stacksize > 0, "Out of stack space" );
    Trace.Assert ( stacksize > 0, "Out of stack space" );
    

    下面的示例显示 Assert 和 Assert:

    [C#]

     
    Debug.Assert ( stacksize > 100, "Out of stack space" , "Failed in inctemp" );
    Trace.Assert ( stacksize > 0, "Out of stack space", "Failed in inctemp" ); 
    

    自定义 Assert 行为

    如果在用户界面模式中运行应用程序,则当条件失败时,Assert 方法将显示**“断言失败”**对话框。 断言失败时发生的操作是由 Listeners 或 Listeners 属性控制的。

    可以通过向 Listeners 集合添加 TraceListener 对象、从 Listeners 集合移除 TraceListener 或者重写现有 TraceListener 的 TraceListener.Fail 方法来自定义输出行为,使其行为不同。

    例如,可以重写 TraceListener.Fail 方法来写入事件日志而不是显示**“断言失败”**对话框。

    若要以这种方法自定义输出,则程序必须包含侦听器,并且必须从 TraceListener 继承并重写它的 TraceListener.Fail 方法。

    在配置文件中设置断言

    您可以在程序配置文件和代码中设置断言。

    JIT 优化和调试

    当调试托管应用程序时,Visual Studio 会默认取消优化实时 (JIT) 代码。 取消 JIT 优化意味着您调试的是非优化代码。 由于代码未优化,因此代码会运行得稍慢一些,但您的调试体验会更全面。 由于调试优化代码要更难一些,因此建议仅在遇到优化代码中发生的 bug 无法在非优化版本中重现时使用。

    JIT 优化在 Visual Studio 中由**“在模块加载时取消 JIT 优化”选项控制。 您可以在“选项”对话框中“调试”节点下的“常规”**页上找到此选项。

    如果清除**“在模块加载时取消 JIT 优化”选项,您可以调试优化 JIT 代码,但调试的能力会由于优化代码与源代码不匹配而可能受到限制。 因此,调试器窗口(如“局部变量”和“自动”**窗口)显示的信息可能没有调试非优化代码时显示的信息那么多。

    另一个重要差异是有关使用“仅我的代码”进行调试。 如果您正在使用“仅我的代码”进行调试,调试器就会将优化代码作为非用户代码处理,不在调试时显示。 因此,在调试 JIT 优化代码时,您可能想关闭“仅我的代码”。

    切记,当模块加载时,**“在模块加载时取消 JIT 优化”**选项会取消代码优化。 如果附加到已正在运行的进程,它可能包含已加载的代码、JIT 编译的代码和优化的代码。 **“在模块加载时取消 JIT 优化”选项对这些代码无效,尽管它会影响在附加后加载的模块。 此外,“在模块加载时取消 JIT 优化”**选项不影响用 NGEN 创建的模块,如 WinForms.dll。

  • 相关阅读:
    Elementary Methods in Number Theory Exercise 1.2.25
    Elementary Methods in Number Theory Exercise 1.2.14
    图解欧几里德算法
    图解欧几里德算法
    Elementary Methods in Number Theory Exercise 1.2.14
    Android中的长度单位详解(dp、sp、px、in、pt、mm)
    分享下多年积累的对JAVA程序员成长之路的总结
    android异常之都是deamon惹的祸The connection to adb is down, and a severe error has occured.
    TomatoCartv1.1.8.2部署时报错
    JavaScript浏览器对象之二Document对象
  • 原文地址:https://www.cnblogs.com/yilang/p/12467615.html
Copyright © 2011-2022 走看看