-3

This question has many great answers explaining why a bug might only manifest itself in a Release build.
Common reasons for bugs in release version not present in debug mode
I have a more specific question regarding undefined behavior.

If a program always appears to work correctly in a Debug build, but behaves differently in a release build (always behaves in the same incorrect way, however), can the problem be due to undefined behavior?

Community
  • 1
  • 1
Elliot Hatch
  • 1,038
  • 1
  • 12
  • 26
  • 5
    Undefined behaviour can cause anything, so yes. – juanchopanza Oct 20 '12 at 21:45
  • Of course it can be due to undefined behavior. But exactly what is the coding question here? – Code Monkey Oct 20 '12 at 21:46
  • The behaviour is _unspecified_ so it can cause anything to happen, it can even cause [nasal demons](http://www.catb.org/jargon/html/N/nasal-demons.html). – Some programmer dude Oct 20 '12 at 21:50
  • 6
    *"Can undefined behavior"* -- Yes. – Keith Thompson Oct 20 '12 at 21:52
  • Okay, sorry about the bad question then. Now I'm wondering, is it common to see the same exact results due to undefined behavior on two different machines? – Elliot Hatch Oct 20 '12 at 21:57
  • 1
    @Rabenholz: Why does it matter? You can't reason about undefined behavior because it is by definition undefined. So you may see the exact same results of UB on two different machines, or you may see completely different results. It doesn't matter, undefined behavior code is allowed to do **anything** as far as the C++ standard is concerned. – In silico Oct 20 '12 at 22:03

1 Answers1

2

Can be due to undefined behavior? Sure. Is it always because of undefined behavior? Certainly not.

Imagine this:

assert(scanf("%d", &n) == 1);

This line will simply get removed in release mode. It is not undefined behavior, but it most certainly will make your program behave in a different way.

assert may be the obvious example here, but think of this more complicated situation:

#ifndef NDEBUG
# define DBG(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
#else
# define DBG(fmt, ...) ((void)0)
#endif

int shared_var;

static inline void do_something_fast(void)
{
    DBG("doing something fast\n");
    shared_var = something_fast();
}

and have thread 1:

...
mutex_unlock();
local_var = shared_var;
...

and thread 2:

...
mutex_lock();
do_something_fast();
...

Now this example is totally absurd, but something along these lines are quite common in multi-threaded environments. In this example, this is what happens:

  • thread 1: calls mutex_unlock, waking up thread 2 and going to sleep
  • thread 2: calls do_something_fast()
    • in release: fprintf is called, causing thread 2 to sleep
      • now thread 1 copies the old value of shared_var into local_var
    • in debug: thread one overwrites shared_var
      • now thread 1 copies the new value of shared_var into local_Var

As you can see, in this example blocking I/O forced a certain behavior between threads, which was itself enabled only in debug mode. This also means that a program working in debug may behave differently than when compiled for release.

Shahbaz
  • 46,337
  • 19
  • 116
  • 182