Differences between D debug and release builds

Started by Simon, March 28, 2022, 06:02:06 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Simon

Hi,

things that I told Dullstar in voicechat about the March 27 sporadic client-side crash.







Debug buildRelease build
in/out contractchecked, like assert(x)not compiled, they have no effects
array bounds checkThrows Error if outsidememory-unsafe access
(I could enable bounds check)
enforce(x)Throws Exception if not xThrows Exception if not x
assert(x)Throws Error if not xnot compiled, statement has no effect
assert(false)Throws Error if not xhalts the application, e.g., segfault

You're supposed to catch Exception but not Error. I still catch both in the main loop, log them, then re-throw them to terminate the application.

assert(x) with a value x only known at runtime: In D, this is deliberately different than assert(false) or assert(0) with a statically known false value. assert(false) marks code that you shouldn't reach. (I'm not sure if the compiler is also allowed to optimize on this assumption in release builds.)

-- Simon

Simon

#1
To run the unit tests:
dub test

To build a debug build:
dub build

To build a release build with array bounds checks:
dub build -b release

To build a release build without array bounds checks:
dub build -b release-nobounds

In these command lines above that start with dub build, you can omit the word build to immediately run the built executable after the successful build.

Lix has two dub projects: The main Lix executable and the standalone server daemon. The above command lines work for either target. If you want the main Lix executable, run the command in the main Lix directory. If you want the standalone server, run the command in:
./src/server/

-- Simon

Simon

Some possible sources of segfault/access violation in D programs:

  • Run into an assert(false) in the source code in a release build.
  • Dereference null.
  • Integer division by zero.
  • Stack overflow from recursion.
  • Illegal memory access from raw pointers or with disabled array bounds checks. Not all bad accesses are caught by the operating system to segfault immediately. The program might continue happily and have corrupted memory.
All of these indicate a bug in in the software. These are never to blame on bad user input; it's a bug; by principle, programs should not segfault. E.g., assert(false) marks code that the author thought should be completely unreachable.

The usual method of investigation is to run a debug build with a debugger attached, provoke the segfault a second time, and look at the backtrace in the debugger. E.g., with the popular debugger gdb:

dub build
gdb -ex run bin/lix
Lix's window will appear, do things in Lix to repro a segfault.
bt

When you're done, exit gdb by entering q or pressing Ctrl+D.

-- Simon