【问题标题】:Is there an automatic way to remove debugging methods for a release build?是否有自动删除发布版本的调试方法的方法?
【发布时间】:2011-05-30 05:26:22
【问题描述】:

注意:这是我之前在这里提出的问题的扩展:Do additional function/method definitions increase a program's memory footprint?

当我编写一个类时,我通常最终会编写几个测试/调试方法,用于确保该类正常工作,或打印数据以帮助调试,或用于单元测试等。无需这些方法即可轻松/自动地进行发布,还是在我想编译发布版本时需要手动删除额外的代码?

我从 C++ 和 Java 的角度提出这个问题。我正在使用 Code::Blocks 和 Eclipse 作为 IDE,如果这能以某种方式解决问题的话。

【问题讨论】:

    标签: java c++ debugging ide release


    【解决方案1】:

    要添加到 Peoro 在 C++ 中的答案,您的发布项目应始终定义 NDEBUG,并且您的调试项目应始终定义 _DEBUG,以便您可以测试其中任何一个或创建自己的预处理器指令以排除代码。

    我个人发现不时拥有一些我自己的预处理器指令非常有益,如果您使用预编译的头文件,则将它们放在 stdafx.h 中的好地方。您可以启用禁用整个功能或部分代码,这些功能或部分代码可能正在进行中或对于某些构建来说简单不受欢迎。例如,在一个应用程序中,通过修改单个定义,我可以从 OpenGl 切换到 DirectX,或者从项目中完全排除 3d 渲染。

    此外,除了调试和发布之外,您还可以为具有某些定义集以及包含或排除等的项目创建新配置。您可能需要两个调试版本,例如一个包含调试跟踪和一个具有详细日志记录的版本在执行期间打印出几乎整个堆栈。

    【讨论】:

      【解决方案2】:

      从 Java 的角度来看,有多种策略:

      • 如果生成日志消息的代码是 sn-ps,请使用 log4j 或其他日志框架之一。

      • 如果它是在生产代码中未使用的完整方法,请将其保留在那里。在运行时,JIT 编译器会注意到它没有被使用并且不会费心去编译它。代码在运行时可能仍然存在(作为未编译的字节码),但对内存占用的影响将是微不足道的......因为 JVM 需要几兆字节的堆空间才能启动。

      • 如果它是一个类或类的集合(例如 JUnit 测试类),请将它/它们放在一个并行包中,并在包名称中的某处使用“test”,并在创建时过滤掉它/它们JAR 文件。

      • 如果你使用 Maven,请将测试类放在“src/test/java”目录而不是“src/main/java”目录下,maven 命令会自动排除它们。

        李>

      一些开发人员建议在 Java 中使用源代码预处理器,但大多数人会说这是一个坏主意;即它引入的问题多于解决的问题。首先,主流的 Java IDE 和调试器不理解预处理器指令,因此您将遇到各种与工具相关的问题。此外,它不是“Java方式”。

      【讨论】:

      • 请注意,对于这个问题的 C++ 方面,peoro 的答案是正确的,我也无法将其标记为正确。
      【解决方案3】:

      在 Java 世界中,您可以将log4j 用于所有日志记录目的,将调试日志记录在您的代码中作为log.debug()。在您的生产代码中,您可以在高于DEBUG 的任何位置运行具有log4j 属性级别的代码,例如INFO。您可以了解更多详情here。

      【讨论】:

      • OP 正在寻求一种方法来删除他的函数,以减少他的程序的内存占用。您的解决方案将加快速度并消除 log4j 函数的影响,但不会减少内存占用,并且由于调用 log4j 函数(将测试调试级别,失败)而留下一点开销。
      【解决方案4】:

      使用预处理器开关

      #ifdef MY_DEBUG_SWITCH
      // debug code goes here
      #endif
      

      【讨论】:

        【解决方案5】:

        对于 C++,您可以使用预处理器宏:

        #ifnef NDEBUG
        void dbgFunction() { ... }
        #endif
        

        NDEBUG 是assert 使用的标准 宏:如果设置了NDEBUG,则不会评估您的assertions。


        另一个想法可能是从您不使用的符号(或从您明确要删除的符号)中剥离二进制文件(因此不接触源代码)。

        【讨论】:

        • 这个答案也完全正确,但很遗憾我无法将两个答案标记为正确。
        • 但是如果您只是将调试代码放入 assert 语句中,则无需这样做。拥有在发布/调试版本之间改变特性的对象不是一件好事。保留函数只是确保代码只从断言中调用。
        • 那么如果调试方法只从 assert 语句中调用,编译器会在发布构建时优化掉它们?
        • 只调用你的调试函数。这些函数将保留在您的二进制文件中,尽管它们永远不会被调用。
        猜你喜欢
        • 2020-11-01
        • 2010-09-08
        • 2010-09-08
        • 1970-01-01
        • 2023-03-17
        • 1970-01-01
        • 2020-08-07
        • 2018-09-08
        • 2010-12-27
        相关资源
        最近更新 更多