47

我认为最好发布您的开发人员实际测试过的软件版本;因此,我倾向于从项目/makefile 中删除“调试”目标,以便只有一个版本可以构建(并测试、调试和发布)。

出于类似的原因,我不使用“断言”(另请参阅断言总是不好的吗? ...)。

那里的一个人争辩说,“调试”版本的原因是它更容易调试:但是,我反驳说,您最终可能希望支持和​​调试您发布的任何内容,因此您需要构建一个发布您可以在必要时进行调试……这可能意味着启用调试符号并禁用某些优化,即使在“发布”版本中也是如此。

有人说“这是个坏主意”;这是我几年前制定的一项政策,被以下因素烧毁:

  • 一些开发人员正在测试他们的调试版本而不是发布版本
  • 一些开发人员的编写错误,仅在发布版本中出现
  • 该公司在测试不充分后发布了发布版本(它是否完全足够?)
  • 被要求调试发布版本

从那时起,我看到不止一个其他开发商店遵循这种做法(即没有单独的调试和发布版本)。

你的政策是什么?

4

19 回答 19

32

拥有单独的调试和发布版本是一个好主意,因为它确实使开发更容易。

但是调试版本应该只用于开发,而不是用于测试。您仅测试发布版本。而且您不使用开发人员来测试这些构建,而是使用测试人员。

这是一个简单的政策,可以两全其美,IMO。

编辑:作为对评论的回应,我认为很明显调试和发布版本(可以)生成不同的代码。想想“-DDEBUG”与“-DNDEBUG”,以及“#if defined(DEBUG)”等。

因此,测试最终交付的代码至关重要。如果您确实在调试和发布版本中生成了不同的代码,这意味着要测试两次——不管它是否由同一个人测试。

然而,调试符号并不是什么大问题。始终使用调试符号构建,保留未剥离的二进制文件的副本,但发布剥离的二进制文件。只要您以某种方式用内部版本号标记每个二进制文件,您就应该始终能够识别哪个未剥离的二进制文件对应于您必须调试的剥离的二进制文件......

如何在调试器中从外部源中剥离二进制文件和加载符号取决于平台。

于 2009-01-07T13:48:52.403 回答
21

这可能是次要的,但它补充了其他人在这里所说的内容。拥有 QA 测试发布版本的优点之一是,随着时间的推移,由于开发人员需要找出 QA 中出现问题的原因,软件的内置调试和日志记录功能将得到提升。

开发人员需要调试发布构建的越多,当客户开始遇到问题时,您将拥有更好的工具。当然,开发人员没有理由将发布版本作为开发周期的一部分。

此外,我不知道有哪家软件公司有足够长的周期来承担在版本测试期间将 QA 从调试版本切换到发布版本的开销。必须进行完整的 QA 周期是经常发生的事情,而且很少发生。

于 2009-01-07T13:54:34.950 回答
14

我们的政策是让开发人员在调试版本上工作,但其他所有人(QA、BA、销售等)都运行发布版本。昨天我不得不修复一个只出现在发布版本中的错误,很明显发生了什么,因为它只出现在发布版本中

这是这家商店的第一个,我在这里已经 18 个月左右了。

当发布版本与调试版本做不同的事情时,事情变得棘手 - 是的,我去过地狱,在一些非常古老、非常粗糙的生产代码中看到了这一点。

如果配置之间的唯一区别是调试符号和优化,我认为没有理由不同时拥有两者。

于 2009-01-07T13:47:56.820 回答
10

所以你需要构建一个版本,如果有必要可以调试......这可能意味着启用调试符号,并禁用一些优化,即使在“发布”版本中也是如此。

嗯...听起来您正在对我进行调试构建...对吗?

您出错的部分是以下语句:

我认为最好发布您的开发人员实际测试过的软件版本

开发人员不测试代码。测试测试代码。

您的单元测试应该测试所有构建配置。不要让您的开发人员将一只手绑在背后工作 - 让他们使用他们可以使用的所有调试工具。调试版本就是其中之一。

关于断言:断言的使用很大程度上取决于您是否按合同进行编程。如果你这样做了,那么断言只是在调试构建中检查合同。

于 2009-01-07T14:46:54.363 回答
5

根据我在链接线程中的回答,出于非常相似的原因,我们也使用相同的构建进行调试和发布。与算法级别的手动优化相比,优化器带来的 10%-20% 的性能提升往往非常小。单个构建消除了许多潜在的错误。具体来说;

  • 未初始化的变量和小的缓冲区溢出可能最终在调试和优化发布版本中产生非常不同的结果。

  • 即使有可用的符号信息,调试优化的版本也可能很困难,因为对象与源不匹配,例如变量可能已被优化并且代码可能已被重新安排。因此,在经过测试的发布版本中报告的错误可能更难以追踪,因此更耗时。

在自动回归测试下比较了未优化和优化的构建,优化提供的性能提升并没有提供足够的额外价值来拥有两个构建。值得注意的是,我开发的软件非常消耗 CPU(例如创建和操作大型表面模型)。

于 2009-01-07T13:54:05.357 回答
4

使用 Java 开发时,我讨厌非调试版本。当抛出异常时,您不会获得任何行信息,这使得很难甚至不可能跟踪错误。此外,使用 Java 5 或更高版本,调试和非调试之间的运行时差异约为 5%,所以这真的没有问题,对于今天的硬盘,大小不再重要。

从好的方面来说,使用调试版本:

  • 堆栈跟踪包含您需要的所有信息
  • 可以检查变量
  • 如果您在生产中遇到问题,您可以简单地附加到正在运行的进程,而无需先停止服务器来安装调试版本。
  • 你不会被聪明的优化错误抓住
  • 构建更简单(只有一个工件)
于 2009-01-07T14:22:58.857 回答
4

开发人员使用调试版本,QA 和其他人使用发布版本,我们称之为“生产”。这样做的主要优点是在调试构建中,我们可以添加大量额外的代码和断言。一些对象包含额外的信息,除了在调试器中查看代码时没有用。有些对象会定期验证自己,以确保所有状态信息都是一致的。这些东西使调试版本慢得多,但它们帮助我们找到了在生产构建中很难找到的错误。

正如我所说,我们所有的 QA 和性能测试都使用生产版本,我们偶尔会遇到在生产中出现但在调试中没有出现的问题。但它们相对较少,作为开发人员,调试调试版本而不是生产版本的优势远远超过了这个问题。

于 2009-01-07T14:56:17.230 回答
3

我认为这取决于项目规模以及您使用的构建系统和测试类型。

如果您有一个自动构建系统,并且在给定构建上运行单元和功能测试很简单,那么您应该永远不会遇到多种构建类型的任何问题。

于 2009-01-07T13:48:07.163 回答
3

由于您在问题中列出的所有原因,我一直订阅“交付您调试的内容,以便您可以调试您发布的内容”方法。

于 2009-01-07T13:55:47.180 回答
3

在我看来,这个讨论缺少一个非常重要的观点:

这真的取决于它是什么样的项目!

如果您创建本机 (C/C++) 项目,您实际上将被迫创建调试版本,这仅仅是因为编译器优化在某些情况下会使调试几乎不可能。

如果您创建 Web 应用程序,您可能希望简单地构建一个可以在运行时启用日志记录功能的构建(尽管“构建”对于某些 Web 应用程序具有误导性)。

虽然原生 C++ 项目和 PHP Web 应用程序显然不是所有类型的项目,但我希望我的观点得到了理解。

PS:在为 C# 开发时,您会遇到边界情况,因为尽管使用调试版本会禁用编译器优化,但根据我的经验,您不会遇到与 C++ 几乎一样多的差异

于 2009-02-12T18:49:02.960 回答
1

在这里,我们以调试模式开发并在发布模式下进行所有单元测试。我们是一家只有几个(12 岁以下)应用程序的小商店,支持从 Classic ASP、ASP.Net、VB.Net 和 C# 等各种应用程序。我们也有专人处理所有的测试,调试的问题会反馈给开发人员。

于 2009-01-07T13:48:18.847 回答
1

我们总是同时构建两者,甚至从未考虑过不这样做。启用调试选项会增加您的代码大小并降低性能,在测试时可能不是您的软件类型的问题,但如果客户正在运行您的代码和 5 个其他应用程序怎么办......

测试问题可以通过使用自动化测试来解决,因此当您认为您已准备好发布时,可以轻松地测试您的发布版本。您的开发人员或公司未能正确测试发布版本并不是发布和调试版本理念的失败,而是您的开发人员和/或公司的失败。

关于你的最后一点,我从来没有被要求调试发布版本,只是为了修复它......

于 2009-01-07T13:50:00.997 回答
1

这是一个权衡。鉴于 CPU 周期很便宜并且越来越便宜,而人工周期仍然很昂贵,因此只维护大型复杂程序的单个版本——调试(山墙)版本是很有意义的。

总是使用断言总是比从不使用它们更安全的策略。如果生成单独的调试和发布版本,请重新启用#define您需要的任何 d 符号,以确保在发布版本中也启用了断言。

于 2009-01-07T13:50:51.417 回答
1

我认为权衡很简单:是的,只有发布版本,您才能真正测试实际发布的内容。另一方面,您确实为开发人员的调试方便和/或用户的性能付出了代价,因此您需要检查这两种情况。

在大多数大中型项目中,易于调试确保最终为您的用户提供更好的产品。

于 2009-01-07T16:07:33.247 回答
1

看到这个你最有争议的编程观点是什么?

引用:

意见:“调试”和“发布”版本之间永远不会有不同的代码

主要原因是发布代码几乎从未经过测试。最好在测试中运行与在野外运行相同的代码。

于 2009-01-07T16:19:31.850 回答
1

通过删除“调试目标”,您将迫使开发人员在软件的发布版本上进行调试。这在实践中可能意味着两件事:

1)“发布版本”将禁用优化(否则开发人员不能使用调试器)

2) 任何构建都不会有特殊的 PREPROCESSOR 宏来改变它们的执行。

所以你真正要做的是合并发布和调试配置,而不是仅仅消除“调试”模式。

我个人在 iOS 开发中做到了这一点,没有任何不良影响。我们编写代码所花费的时间不到实际情况的 1%,因此优化并不是重要的贡献者。在这种情况下,它们确实似乎确实导致了错误的增加,但即使没有,用一种方法进行测试,然后用不同的代码提供给 QA 的想法只是引入了一个要考虑问题的因素。

另一方面,在某些情况下,优化是必要的,它们是有用的,甚至有足够的时间来测试两者。通常,调试和发布之间的变化非常小,根本不会给任何人带来任何问题。

于 2017-11-29T03:28:07.737 回答
0

如果你有一个真正的 QA 团队可以完全测试这个东西,我会说在你接近发布之前进行调试构建,然后确保在同一个构建上完成一个完整的 QA 周期。出门。

尽管至少在一种情况下,我们发布了一些仍然包含一些调试代码的东西。唯一的后果是它的运行速度有点慢,而且日志文件非常大。

于 2009-01-07T13:47:34.030 回答
0

在我的公司,我们既有 Debug 又有 Release。- 开发人员使用调试版本正确查找和修复错误。- 我们正在使用 TDD,因此我们有一个在我们的服务器上运行的大型测试套件,用于测试调试和发布构建配置以及我们拥有的 64/32 构建。

因此,如果使用“调试”配置可以帮助开发人员更快地找到错误,那么没有理由不使用它——当代码进入服务器(待进一步测试)或审查时,我们使用“发布”配置。

于 2009-01-07T13:48:59.533 回答
0

我很久以前就学会了使用 .PDB 文件构建发布版本,以便我可以调试发布版本。许多程序员往往忘记的是,当您运行调试版本时,关闭所有优化,您完全在调试一个不同的程序。它可能表现得像发布版本(大部分情况下),但它仍然是与发布版本不同的程序。

此外,调试发布版本并不难。如果你得到一个崩溃转储,你无论如何都必须能够做到。

于 2009-01-07T13:51:42.133 回答