Why not always build a release with debug info?
Asked Answered
S

5

19

If debug information is stored in a program database (not as part of an executable), is there any reason not to always build with it (e.g., MSVC's /Zi)?

In CMake, the default configurations are, "Release", "Debug", "RelWithDebInfo", and "MinSizeRel". Is there a reason not to only use "Debug" and "RelWithDebInfo" (perhaps renamed to "Release")?

Does it have any impacts on the size or performance of the code? Is the answer different for gcc or clang than it is for Visual C++?

Update

I did come across these posts that are similar:

However, neither of these get to the question of Release vs. RelWithDebInfo.

Yes. I could do a test on an executable with Release vs. RelWithDebInfo. That would definitely give me the answer about the size of the code, but would be very difficult to conclude that it has NO impact on performance if my test case showed similar performance. How would I know if I exercised aspects of the language that might be impacted by the change? That is, empirical testing could produce a false negative.

Sitology answered 7/12, 2017 at 20:56 Comment(8)
cant you build with and without and see the difference?Beater
I can figure out empirically, but my question is more about the theory. Is there SUPPOSED to be a difference?Sitology
Very close, if not an outright duplicate: https://mcmap.net/q/102278/-anything-wrong-with-releasing-software-in-debug-mode/10077Dunaj
@FredLarson Releasing software in debug mode is not the same as releasing software with debug info.Blakely
The only reason I can think of is that generating debug info takes time. So building with debug information is slower. But other than that, code size and performance are the same with/without debug info.Cone
Thanks, @geza. That's the answer I was looking for (and confirms my suspicion).Sitology
yes really. When I dropped the comment there was zero evidence of any research from your side. Not sure what it has to do with eagerness, actually I am rather hesitant to use those links and I think it is the first time it did so.Beater
Fair enough. I posted a little hastily, but your rationale wasn't very fair either. A test build would not be conclusive.Sitology
B
9

Releasing with debug info is mandatory for real-life development. When shit happens your primary tool would be a crash dump analysis that would be rather pointless without debug information. Note that this does not imply shipping debug info with product.

As for "little differences" between vc++ and gcc I would like to mention that by default vc++ emits debug information in a separate file while gcc will squeeze it into executable. It is possible to separate debug information on gcc as well, however doing so is not as convenient and requires some extra steps.

Blakely answered 7/12, 2017 at 21:18 Comment(4)
So do you only build RelWithDebInfo and Debug (or their equivalents for non-cmake build systems)? Are there other configurations you use? Would your answer change for gcc since it makes the executable larger?Sitology
@NealKruis: the best way in my opinion is to generate with debug info. And then create a without-debug info executable from the with-debug info executable. Check out the like VTT provided in the answer. A without debug info build is only useful in the case when the debug info is surely not needed.Cone
@NealKruis: note: even, if the executable is larger, the code is not. Furthermore, the OS will only load parts from the exe which are needed for execution. So the debug info won't be loaded.Cone
@NealKruis Even if I have to use cmake I typically don't rely on build-in configurations and manually write all the compiler options.Blakely
O
6

If you build as Release, surely you won't have Debug Info in the binary. I could see a lot of cases on Windows that people build "Release", but add flags to have debug info. So, i think the default real-life case for most Windows Users, even without knowing that, is Release With Debug Info.

With CMake, you have all three options and one more.

  1. Release means no debugging symbols at all, and MAY also means build with optimizations.
  2. RelWithDebugInfo means build with debug symbols, with or without optimizations. Anyway, the debug symbols can be stripped later, both using strip and/or obj-copy. If you use strip, the output can be saved. I guess the format is DWARF, version 4 or 5.

So, RelWithDebugInfo gives you Release mode binaries, and symbols can be stripped and kept apart. In some projects i have worked, that was the ONLY configuration used.

We must not forget about ASSERTS, at least for C/C++. Building with DEBUG, all Asserts are enabled, so they are not removed from the code during preprocessing. Release and RelwithDebugInfo remove the Asserts, so you won't have them. Some projects nowadays prefer to keep Asserts while developing (so that tests can catch "software" errors during development), and then finally remove in Production Code. Some other projects, for whom Fault-Tolerance is a must, may want to keep Asserts even in production code, so that software cannot execute with wrong Assertions about the software itself.

So,

RelWithDebugInfo: Optimized Build, With Symbols to be stripped, no Asserts

Debug: Not optimized, With Symbols that CAN be stripped, With Asserts.

Release: Optimized, No Symbols, No Asserts.

Overprize answered 27/9, 2022 at 11:42 Comment(0)
I
1

This is a bit old but I was asking myself the same.

It should be basically the same but it is not. You need to look at the different Compiler flags set in your CMake defaut conf for Release or ReleaseDbgInfo. For example for msvc Release is Ob2 and DbgInfo Ob1. Meaning with DbgInfo inlining will be less aggressive as not all functions are considered. That way you can pretty much get the exact line of crash in your source code file from the mem dump, thats nice, but that could mean also missed inlining opportunities so less perf.

I'd argu thats negligible in most cases and I saw almost no difference while debug info in prod is huge help . But still, you want to know the difference ? Look at the compiler flags difference.

Ism answered 9/3, 2023 at 21:46 Comment(0)
B
0

Recently we have cases on Release vs RelWithDebInfo, we compile a shared lib, and found either the performance and the lib file size has a significant difference, Release is much more runtime faster and less file size.

So it looks like Release should be used when shipping on production.

Balzac answered 13/8, 2022 at 3:7 Comment(0)
B
0

I have come here with the same question in 2024, more than 6 years after the original post. However I'm slightly dissatisfied with the current answers, as they leave out the (very relevant) flip side of RelWithDebInfo: The resulting executable may be considerably slower.

This slowdown can be both measured in benchmarks but also understood from a simple consideration: In order to allow for useful debugging, the compiler can not optimize as aggressively, because i.e. function names need to remain (mostly) available.

To summarize a number of arguments regarding a build with RelWithDebInfo:

Pro:

  • Good runtime performance of the executable, much better than Debug builds.
  • A large part of the debug information is available:
    • Executable can be stepped through
    • Breakpoints can be set
    • Stack traces can be generated
  • Furthermore, the debug information can be separated from the executable (i.e. when setting cmake variable CMAKE_MSVC_DEBUG_INFORMATION_FORMAT to ProgramDatabase), at least on Windows
    • This allows to ship a release build to customers, while having the debug files ready for support technicians, that will be able to even debug production code on customer hardware.

Con:

  • Not the same runtime performance as in Release builds, due to the required additional information about i.e. function names etc.
    • In our benchmarks, runtime critical code would execute about 12% slower when built with RelWithDebInfo vs Release (compiled for x64 with clang-cl 16.0.6 against Visual Studio 2022 17.9.5).
  • Not the full debug information and debug behavior is available when compared to a Debug build:
    • I.e. code sections with compiler define DEBUG are disabled, and NDEBUG enabled.
    • Out-of-bounds checks may be disabled.
    • Compiler optimizations in release mode may allow the compiler to remove or reorder code sections, making it harder to understand the executable behavior in the debugger.
    • etc...

Summary My personal summary is that there is a relevant trade-off between the various build modes. Developers should evaluate their options. If the application is not runtime critical, then RelWithDebInfo has many good arguments on its side, foremost to ability to debug the exact same application shipped to customers, possibly even on customer hardware. However, dedicated Release and Debug builds also have their benefits, for example the possibly better runtime performance of dedicated Release builds, or the better debugging behavior in dedicated Debug builds.

Further considerations As of summer 2024, there is still debate about the most suitable compiler flags for the various compiler flags in RelWithDebInfo vs Release, at least when cmake is used as a build tool. Most of above considerations reflect the current default compiler flags, and with modifications of those flags, the behavior may (significantly) change. See for example the discussion about RelWithDebInfo should use /Ob2 for more aggresive inlining in MariaDB, which would reduce the ability to debug, but in turn would increase the runtime performance.

Boltzmann answered 23/6 at 8:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.