在调试模式下发布软件有什么问题吗?

时间:2009-06-03 21:37:45

标签: debugging

我们都知道“调试模式”应该用于开发,因为编译器会产生更多的调试信息,并且“Release Mode”应该用于生产版本,因为编译器会生成优化的代码。

但是,假设您正在制作一个仅在内部使用的软件,并且代码性能不是一个大问题,因为该软件需要执行很多文件I / O和数据库查询。我很想在这种情况下以“调试模式”发布软件,因为这些额外的调试信息使得将来的维护更容易。

在这种情况下,是否还有任何令人信服的理由在发布模式下发布软件?

20 个答案:

答案 0 :(得分:29)

我能想到的两个问题:

  1. 调试版本经常向缓冲区添加填充。这就是为什么有时你会得到似乎的程序在调试中工作但在发布时崩溃。看来这是一个有效的词,因为缓冲区溢出只是一个等待发生的事故。

  2. 调试版本中发生了奇怪的事情。我曾经在一个长期运行的应用程序上工作,每20天左右会崩溃一次。事实证明,在C运行时,每次执行malloc / free时,计数器(用于辅助调试)都会递增。如果柜台碰巧溢出 - kaboom!仅仅因为这个原因,我永远不会建议任何人部署调试二进制文件 - 你永远不知道可能会有什么惊喜等待你的客户。

答案 1 :(得分:15)

可能的原因:

  1. 通常不会为性能编译调试
  2. 调试应用程序大小(通常)比发布编译大很多。
  3. 如果有人试图对您的应用程序进行逆向工程(无论出于何种原因),那么它就会变得容易多了。
  4. 更新: 4.正如所指出的那样,链接器的性能,但我认为会在列表中排名:p与调试编译相比,您发布了多少次产品?

    如果你愿意放弃上述内容,那么就没有真正的原因。

答案 2 :(得分:10)

您提出的一个事实表明您希望利用调试模式带来的好处。如果这些好处超过你的道德内疚,那么我说继续前进吧。这些好处可能是机械的和信息性的,并且与您的工作相关,而缺乏内疚并不能真正帮助您生产出更好的软件。它可能会帮助你睡得更好,但谁在乎?

答案 3 :(得分:5)

我猜想安装的调试代码比我们(开发人员)愿意承认的要多得多。

就我个人而言,我知道许多生产系统都是以调试模式编译的代码部署给客户的。

答案 4 :(得分:5)

我没有任何个人反对在内部发布Debug版本,前提是它有效(某些Debug版本不能在非开发机器上运行,而且还安装相应的调试库... ...我编写了C ++ / MFC代码。

稍微复杂一点的方法是使用符号服务器,一个由构建过程自动更新符号的服务器。

如果您正在从客户端计算机调试问题,请将轻量级调试器指向您的符号服务器(确保版本匹配),然后开始调试。

答案 5 :(得分:4)

使用发布模式,但在启用所有调试信息的情况下进行编译,并使用可执行文件部署pdb文件。您可以像调试一样调试发布二进制文件 - 没有区别,您只需在构建时生成pdb文件。

释放并运行调试版本可能会很危险,因为它会隐藏代码中的错误,这些错误只会以发布模式进行。

答案 6 :(得分:3)

我有一个模糊的回忆,如果你把在Debug下编译的二进制文件带到没有安装调试C运行时库的计算机上(这通常意味着它没有IDE,所以大多数用户属于这个类别) ,它将barf与错误消息。我不知道这是否特定于Windows和/或C ++。我也可能记错了......但你一定要检查一下是否会发生这种情况,好像我是对的,这是在发布模式下编译的一个主要原因。

答案 7 :(得分:2)

  

额外的调试信息使未来的维护更容易。

这取决于“额外调试信息”的含义。

如果您的意思是调试消息,您可能应该使用Trace,而不是Debug,并使用配置文件中定义的跟踪开关和跟踪侦听器来控制运行时的日志记录行为。

如果您的意思是在出现异常时知道成员名称和行号,则无需分发调试版本来获取该信息;只需使用您的可执行文件分发.pdb个文件。 Exception类使用.pdb文件中的信息,无论您是否设置了任何编译常量。

答案 8 :(得分:1)

取决于用户

如果用户是技术,为符号提供额外的调试包可以帮助他们代表您调试或提交更多技术错误信息...... 节省您的资金/时间

如果用户是家庭用户 ......他们可能不会关心调试信息是否存在。为您提供所有的痕迹:)

如果是商家正在寻找精益求精的无膨胀机器,那就给它们一个剥离版本。

取决于您的业务/沟通目标和限制因素。

答案 9 :(得分:1)

在问题中你是独立于平台的,但是关于为什么不在ASP.Net上将调试模式投入生产的建议表明了一些(不可否​​认的与性能相关)的原因,不这样做。

1)ASP.NET页面的编译需要更长时间(因为某些批处理优化被禁用)

2)代码执行速度较慢(因为启用了一些额外的调试路径)

3)在运行时在应用程序中使用了更多的内存

4)从WebResources.axd处理程序下载的脚本和图像不会被缓存

对于某些类型的控件来说,最后一点是一个必然的杀手锏,这些控件在web2.0世界中是“预期的”功能,即使对于内部应用也是如此。有关最后一点费用的更多详细信息,请参阅ScottGu的文章。

总结反驳论据的最好方法可能是“这取决于你如何定义代码性能”。

答案 10 :(得分:1)

在调试模式下编译任何应用程序会向应用程序添加代码,这些代码几乎由编译器或IDE专门用于调试,逐步执行代码等。这些调试功能在现实生活中几乎没有用处。如果您想向公众发布应用程序,最好的办法是在发布模式下编译它。此外,发布版本的应用程序......

  • 更快更稳定
  • 针对机器进行了优化
  • 尺寸较小
  • 更安全(更难反编译/破解)
  • 硬件更高效,更轻松

如果您可以选择发布模式,为什么不使用它?您将始终拥有用于开发的调试版本,或者如果出现问题,您始终可以使用Release版本的版本打包Debug构建的应用程序和/或源代码。

此外,您还可以选择为某些平台构建应用程序。使用Release模式进行编译将简化所述平台的应用程序,使其更加稳定。

即使速度不是问题,编译时也没有理由不使用发布模式。

答案 11 :(得分:1)

我主要有两个调试版本的问题:

  1. 调试信息可能是一项重大且不必要的保险检查,可以通过其他方式避免以后的维护。
  2. 诊断是应用程序的一个方面,它与您正在构建的构建配置无关或依赖
  3. 我认为在您的应用中设计和保持仪器和诊断逻辑作为一个方面或跨领域的关注点非常重要。如果您过分依赖代码调试版提供的信息:

    • 您是否可以保证每次发布新版本的应用程序时都会发布调试版本?糟糕的文件,其他人这样做等等。
    • 应用程序的功能和复杂性趋于增长。虽然由于调试版本而导致应用程序的性能和大小可能不是问题。事情可能会加起来并导致潜在的问题。如果出现性能问题,您甚至可能不会将它们归因于调试版本。

    您仍然可以在发布版本中收集有价值的信息。如果出现异常,堆栈跟踪仍应可用。您可能看不到源文件和行号,但您仍然可以看到调用哪些方法。但是,您仍应为发布版本生成并保留调试符号。这些符号将允许您调试发布版本(甚至可以设置符号服务器)。由于代码优化,调试信息很可能不匹配100%的代码,例如调试信息指的是一个被优化掉的语句等,但你仍然可以调试大部分的确定。对于其他信息,例如用户输入数据,中间数据,执行的数据库代码等调试版本将无法帮助您,因为它不会捕获该信息。你需要自己跟踪这些。

    如果您使用的是.NET,可以查看Tracing and Instrumentation 。您还可以考虑使用现有框架,如Microsoft Enterprise Library或log4net。如果它是.NET应用程序,您还可以请求JIT编译器生成应用程序发行版的跟踪信息作为选项。查看this MSDN article

答案 12 :(得分:0)

我个人相信调试和发布之间的中位数解决方案,也就是说,您已经足够记录,以便在发生错误时重现错误。当您的应用足够稳定时,请使用配置文件中的参数关闭额外的辣记录。但我意识到它不可能一直都在做。大多数情况下,当您的应用仅在一个地方运行时。

另外,我努力在我的工作场所实施的一条黄金法则(并且尚未完全成功):永远不要让你的代码显示出来。如果用户精通技术,他就会知道发生了什么,并且对你的看法很糟糕。如果你的用户没有,他会认为他的电脑被魔鬼附身,并且认为你很糟糕。

答案 13 :(得分:0)

发布两个版本,一个标记是否出现错误使用此版本。

但是根据敏感数据锁定调试版本。

答案 14 :(得分:0)

除了已经提到的性能,大小和反编译......

安全性:调试构建和调试信息(例如pdb文件)包含大量有关源代码的信息,这不仅使反编译变得更加容易,而且还可以让用户了解内部详细信息,例如文件名和网络路径。许多公司可能认为这些信息非常敏感。

答案 15 :(得分:0)

这是我通常使用需要调试信息的软件(通常是开发类型工具) - 我编译我的代码优化,但有符号信息,并链接,以便我保留符号信息。这样,当软件崩溃时,我至少可以获得一个中等体面的堆栈跟踪,并了解在我向客户发送完整调试版本时从何处开始添加额外的日志记录信息。

有时优化器会导致错误,有时会使它们模糊不清,但至少你有能力缩小问题范围。这对我来说在像Raytheon这样的黑盒环境中创造了奇迹,在那里获得核心转储是不可能的,并且堆栈跟踪传真带有大黑色标记。

答案 16 :(得分:0)

您是否正在发布该软件? (这是一个“是”,“否”的问题,“是的,但......”不计算在内)

如果是这样,为什么不正确地做它并使它成为真正的版本,这样你就不必依赖于为用户提供的调试符号....

答案 17 :(得分:0)

我的决策树是这样的:

程序是用Java编写的吗?

是 - 然后在调试模式下发布就可以了。 JIT将负责优化

否则 - 程序CPU是否密集?

否 - 调试模式下的释放很好。

是 - 然后仅在发布模式下编译热点。

基本原理:当从您在IDE中运行的完全程序生成错误报告时,维护代码要容易得多。在IDE中,您使用调试版本,因此您应该努力在调试模式下发布。

答案 18 :(得分:0)

我认为遵循良好的标准,惯例和程序非常重要。仅仅因为应用程序仅在内部使用并不是让自己变得懒惰的好理由。虽然我对做事的“正确方式”有强烈的感受,但我相信编写优秀软件的习惯超过了长期使用调试版本作弊的好处。添加一些异常处理,了解您编写的系统的缺陷 - 它将使您编写的所有代码更好。

答案 19 :(得分:0)

如果它是一个网站或服务并且性能不是问题,那么一定要以调试模式释放它。如果它是桌面应用程序,那么考虑调试模式版本是否在用户友好的方式处理错误。如果是,那么我也会发布调试版本。