I think it's better to release the version of the software which your developers actually tested; I therefore tend to delete the 'debug' target from the project/makefile, so that there's only one version that can be built (and tested, and debugged, and released).
For a similar reason, I don't use 'assertions' (see also Are assertions always bad? ...).
One person there argued that the reason for a 'debug' version is that it's easier to debug: but, I counter-argued that you may eventually want to support and debug whatever it is you released, and so you need to build a release which you can if necessary debug ... this may mean enabling debug symbols, and disabling some optimizations, even in the 'release' build.
Someone else said that "this is such a bad idea"; it's a policy I evolved some years ago, having been burned by:
- Some developers' testing their debug but not release versions
- Some developers' writing bugs which show up only in the release version
- The company's releasing the release version after inadequate testing (is it ever entirely adequate?)
- Being called on to debug the release version
Since then I've seen more than one other development shop follow this practice (i.e. not have separate debug and release builds).
What's your policy?
Having separate debug and release builds is a good idea, because it does make development easier.
But debug builds should be for development only, not for testing. You test release builds only. And you don't use developers to test those builds, you use testers.
It's a simple policy that gives the best of both worlds, IMO.
Edit: In response to a comment, I think it's obvious that debug and release builds (can) generate different code. Think "-DDEBUG" vs. "-DNDEBUG", and "#if defined(DEBUG)", etc.
So it's vital that you test the code that you end up shipping. If you do generate different code in debug and release builds, that means testing twice - regardless of whether or not it's tested by the same person.
Debug symbols are not that big an issue, however. Always build with debugging symbols, keep a copy of the unstripped binary, but release a stripped binary. As long as you tag each binary with a build number somehow, you should always be able to identify which unstripped binary corresponds to the stripped binary that you have to debug...
How to strip binaries and load symbols in your debugger from an external source is platform-dependent.
It's a tradeoff. Given that CPU cycles are cheap and getting cheaper while human cycles remain expensive, it makes a lot of sense to maintain only a single version of a large, complex program -- the debug(gable) version.
Always using assertions always is a safer policy than never using them. If producing separate debug and release versions, re-enable whatever
#define
d symbols you need to guarantee that assertions are enabled in the release version also.As per my answer in the linked thread, we also use the same build for debug and release for very similar reasons. The 10%-20% performance gains from the optimiser tend to be very minor when compared to manual optimisations at algorithm level. A single build removes many potential bugs. Specifically;
Uninitialised variables and small buffer overflows may end up with very different results in debug and optimised release builds.
Even with the symbolic information available, debugging an optimised release can be difficult as the object doesn't match the source, e.g. variables may have been optimised out and code may have been re-arranged. Thus bugs reported in tested release builds can be more difficult, and hence time-consuming, to track down.
Having compared unoptimised and optimised builds under automated regression tests, the performance gains provided by the optimisation don't provide enough extra value to have two builds in my case. It is may be worth noting that the software that I develop is very CPU hungry (e.g. creating and manipulating large surface models).
I've always subscribed to the "Ship what you debug, so you can debug what you ship" approach, for all the reasons you list in your question.
here we develop in debug mode and do all unit testing in release mode. we are a small shop with just a few (under 12) application to support ranging from Classic ASP, ASP.Net, VB.Net, and C#. We also have a dedicated person to handle all testing, debugged problems are thrown back to the developers.
Our policy is to have developers work on Debug builds, but EVERYONE else (QA, BAs, sales etc) runs the release version. Yesterday I had to fix a bug that only showed up in the release build it, was obvious what was happening simply BECAUSE it only showed up in release
It's first one here in this shop, and I've been here 18 months or so.
Where things get hairy is when the Release build does different things to the debug build - Yes, I have been to Hell and seen this in some very old, very ropy production code.
I see no reason why not to have both if the only difference between the configurations are debug symbols and optimisations.