views:

1953

answers:

18

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 http://stackoverflow.com/questions/419406/are-assertions-always-bad#419410 ...).

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?

A: 

If you've got a real QA group who can be counted on to fully test the thing, I'd say make debug builds until you get close to the release, and then make sure a full QA cycle is done on the same build that's going out the door.

Although in at least one case we released something that still had some debug code in it. The only consequence was it ran a tiny bit slower and the log files were pretty damn big.

Paul Tomblin
@Paul Tomblin: I would disagree. Only ever test against Release builds. I've seen side effect code present in debug mode only. Testing the "full QA cycle " twice is fraught with danger...
Mitch Wheat
@Paul, we overcame this by changing #ifdef DEBUG to if (_debugging()) such that the overhead was only in executable size and we could still invoke debug/diagnostic code in the release as and when required. (C or C++ only)
Shane MacLaughlin
Re. "the log files were pretty damn big" perhaps that's because your debug build has extra log statements; instead of that I like to control the level of logging (how much detail is logged) via run-time configuration options.
ChrisW
+6  A: 

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.

Binary Worrier
+3  A: 

I think it depends on the project size and what type of build system and testing that you are using.

If you have an automated build system in place, and it's simple to run unit and functional tests on a given build, then you should never have any problems with multiple build types.

Robert Venables
+1  A: 

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.

brad.v
+16  A: 

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.

That's all fine and dandy, provided that you have the staff to support that kind of testing. But what if (like me), you work in a company that has neither the staff nor the desire to acquire the staff to test in that manner?
Mike Hofer
You should always try to have some one other than the developer do final testing, even if it's just another developer. A new person will come at it from a different angle.
Patrick
@Mike: There's good statistical evidence that developers don't find their own bugs. That's ok for one-man shows where the customer has a direct wire to the developer, and an urgent fix can be out in an hour between phone ringing and DLL delivered. Even for a one-man-show, I'd make a separation of development and testing. There should be at least a minimal, manual protocol for things to test on the final build before it leaves the door.
peterchen
I tackle this by having my CI build server build only the Release configuration. Developers can then feel free to use whatever configuration they like, but as soon as they commit code to version control, everything is Release from that point on.
Tim Long
A: 

In my company we have both Debug and Release. - The developers use the debug version to properly find and fix bugs. - We are using TDD and so we have a big test suite that we run on our server that tests both debug and release build configurations as well as 64/32 builds we have as well.

So if using the "debug" configuration helps a developer to find a bug faster there is no reason not to use it - when the code goes into the server (to be further tested) or reviewed we use the "Release" one.

Dror Helper
A: 

We always build both, never even considered not doing so. Enabling debug options increases your code size and slows performance, possibly not an issue with your type of software when testing but what if the customer is running your code plus 5 other apps...

The issues with testing can be sorted out by using automated testing so you're release build can be effortlessly tested when you think you're ready to release. The failure of your developers or company to properly test release builds is not a failure in the idea of release and debug builds but in your developers and or company.

On your last point, I have never been called upon to debug a release build, just to fix it...

Patrick
+1  A: 

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 #defined symbols you need to guarantee that assertions are enabled in the release version also.

j_random_hacker
A: 

I learned to build the release version with .PDB files long ago so that I could debug the release version. What a lot of programmers tend to forget is that when you run the debug version, with all the optimizations turned off, you are debugging a different program altogether. It may behave like the release build (for the most part), but it is still a different program than the release build.

In addition, debugging the release build is not that difficult. And if you get a crash dump, you have to be able to do it anyway.

Ferruccio
+2  A: 

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).

Shane MacLaughlin
Do you also use a code analyzer to detect "uninitialised variables and small buffer overflows"? Also you might enable compiler optimization of only the most critical module[s] (on a per-module basis), while still keeping the policy of having only one build target.
ChrisW
valgrind or other tools can identify invalid usage of memory far better than just looking for different results, so that's a fairly weak justification.
Tom
@Chris, I use PC-lint to carry out static analysis on the code, and Boundschecker and AQTime for dynamic analysis. I also use a lot of 3rd party libs that I have much less control over (or desire to debug).
Shane MacLaughlin
@Tom, Valgrind is a great tool but unfortunately I'm Windows based. I do use both static and dynamic analysis tools but they have their limitations. e.g. try throwing a couple of hundred thousand lines of someone else code to lint and decipher the megs of error messages returned.
Shane MacLaughlin
smacl - I know what you mean - try turning on -Wall -Wextra -Werror -ansi -pedantic -std=c++98 on any legacy codebase and see how many compilation units you can break.IMO, Compiler warnings need to be controlled with an iron fist in any software shop, to keep everything clean enough to analyze.
Tom
+12  A: 

This might be minor, but it adds up to what others have said here. One of the advantages of having QA test release builds is that over time the built in debugging and logging capabilities of your software will advance due to the needs of developers who need to figure out why things are going wrong in QA.

The more the developers need to debug release builds, the better tools you'll have later when customers start having issues. Of course, no reason for developers to work on release builds as part of the development cycle.

Also, I don't know any software company that has long enough cycles to afford the overhead of switching QA from debug to release builds halfway through a version's testing period. Having to do a full QA cycle is something that all too often happens pretty rarely.

Leeor Aharon
"...all too often happens pretty rarely" - ummm... :D
demoncodemonkey
+1  A: 

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.

Roddy
+1  A: 

When developing with Java, I hate non-debug versions. When an exception is thrown, you get no line information which makes it hard or even impossible to track bugs down. Also, the runtime difference between debug and non-debug is around 5% with Java 5 or later, so this is really no issue and with todays hard disks, size doesn't matter anymore.

On the plus side using debug versions:

  • Stack traces contain all the information you need
  • Variables can be examined
  • If you have a problem in production, you can simply attach to the running process without having to stop the server first to install a debug version.
  • You won't get caught by clever optimization bugs
  • The build is more simple (just one artifact)
Aaron Digulla
+4  A: 

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.

Ummm... it sounds like you're doing a debug build to me... right?

The part where you went wrong is this statement:

I think it's better to release the version of the software which your developers actually tested

Developers don't test code. Tests test code.

Your unit tests should test ALL build configurations. Do not make your developers work with one hand tied behind their back - let them use all the debugging tools they have at there disposal. A Debug build is one of these.

Regarding asserts: the use of assertions greatly depends on whether or not you program by contract. If you do, then assertions merely check the contract in a debug build.

Daniel Paull
"... right?" Call it what you will: it's a release build that includes debug information ... the one-and-only build ... a hybrid.
ChrisW
"Developers don't test code. Tests test code." Some tests can't easily be automated, or haven't been automated.
ChrisW
I agree that some tests can't be easily automated, but whether this is a problem for you depends on the size of your QA team. If your QA "team" is Frank down the hall, then the developers need to do some QA as well. If you have a QA team of twenty, then *they* should be running manual tests.
Graeme Perrow
@ChrisW: I never said automated tests! You should have test scenarios written down for code that requires manual testing - these are still tests. Do not rely on ad hoc testing during development; you are testing intermediate versions of the system and the test results are meaningless.
Daniel Paull
A: 

Developers work with debug builds, QA and everyone else uses the release version, which we call "production". The main advantage to this is that in the debug build, we can add lots of extra code and assertions. Some objects contain extra pieces of information that have no use except when viewing code in the debugger. Some objects validate themselves periodically to make sure that all the state information is consistent. These things make the debug version much slower, but they have helped us find no end of bugs that would have been hell to find in the production build.

As I said, all of our QA and performance testing uses production builds, and we do occasionally run into problems that show up in production but not in debug. But they're relatively rare, and as a developer, the advantages of debugging a debug build rather than a production build far outweigh that problem.

Graeme Perrow
A: 

I think the tradeoff is simple: yes, with only a release build, you really test what's actually being shipped. On the other hand, you do pay a price in ease of debugging for your developers and/or performance for the user, so it's up to you to check both cases.

On most medium- to large-size projects, ease of debugging will ensure a better product for your users in the end.

Carl Seleborg
A: 

See this http://stackoverflow.com/questions/406760/whats-your-most-controversial-programming-opinion#406945

quote:

Opinion: Never ever have different code between "debug" and "release" builds

The main reason being that release code almost never gets tested. Better to have the same code running in test as it is in the wild.

tuinstoel
A: 

In my opinion this discussion missing a very important point:

It really depends upon what kind of project it is!

If you create a native (C/C++) project you will in effect be forced to create debug builds, simply because compiler optimizations can make debugging near impossible in some cases.

If you create web applications you might rather wish to simply have one build (although "build" is rather misleading for some web applications) that can enable logging features during runtime.

Although a native C++ project and a PHP web application are obviously not all kinds of project that exist, I hope my point got across.

P.S.: When developing for C#, you run into a border case since although using a debug build disables compiler optimizations, in my experience you will not run into nearly as much differences as with C++

dionadar
That's true. What I'm saying is that even in C++ project, because you need to support (and therefore might need to debug) the relased software, therefore even the 'Release' build should be debuggable ... and therefore you don't need (and IMO don't want) a separate 'Debug' build.
ChrisW
I totally agree that a "debug build" even in a C++ project should mainly consist of changing compiler options and not the code that is executed.
dionadar