Skip to main content
AKuma.2074
Associate II
September 13, 2021
Solved

What is the difference between debug and release, of a project

  • September 13, 2021
  • 8 replies
  • 32838 views

Hi,

I am completely new into microcontrollers. And while working with keil as well as smt32cube ide i found options such as debug and release.

Can someone please tell me whats the difference between both, what benefit one has on other and when to use when.

Thanks and regards

Best answer by TDK

The difference is the compiler settings. Release is much more optimized, resulting in faster and smaller code, but is harder to debug since some source code statements may be removed/rearranged. Variables may be optimized out entirely.

I would use Debug exclusively unless performance becomes an issue. It is much easier and more productive to keep the configuration the same rather than to try to maintain two configurations. Bugs that don't appear in Debug may appear in Release.

8 replies

TDK
TDKBest answer
September 13, 2021

The difference is the compiler settings. Release is much more optimized, resulting in faster and smaller code, but is harder to debug since some source code statements may be removed/rearranged. Variables may be optimized out entirely.

I would use Debug exclusively unless performance becomes an issue. It is much easier and more productive to keep the configuration the same rather than to try to maintain two configurations. Bugs that don't appear in Debug may appear in Release.

"If you feel a post has answered your question, please click ""Accept as Solution""."
AKuma.2074
Associate II
September 13, 2021

Thanks

Tesla DeLorean
Guru
September 13, 2021

Optimization Level

Stack Checking

Asserts

Verbose Diagnostics

Additional symbolic and line numbering information in objects

Stuff that would tend to aid debugging and testing phases of the software/hardware

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
AKuma.2074
Associate II
September 13, 2021

Thanks

Andrew Neil
Super User
September 14, 2021

it is whatever you configure it to be!

@TDK​  and @Community member​  have given you some typical examples.

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
mattias norlander
ST Employee
September 27, 2021

Quite complete answers already provided by community. Just a few more points.

Default optimization levels in GCC for the configurations:

  • Debug --> Optimization off -O0
  • Release --> Optimize for size -Os

If you run low on memory when using "Debug" due to -O0, then you could switch this configuration to rely on -Og which introduces optimization that should not disturb the debug experience.

There are also different philosophies on addressing optimization levels in build configurations.

Some developers thinks that Release and Debug should have as similar optimization related settings as possible in order to make sure that you "debug what you ship and ship what you debug".

CTapp.1
Senior III
December 19, 2023

Yes, optimisation should ideally be the same as higher levels often expose defects related to undefined-behaviour - the optimiser assumes there is none present, and code generation can "break" if there is (a little example, where the defect completely breaks the code at -O2, but not at -O0 ).

Though it isn't fun using a debugger with aggressive optimisations enabled!

All posts are made in a personal capacity. MISRA C++ Chair, MISRA C WG Member, Director The MISRA Consortium Limited (TMCL)
Tesla DeLorean
Guru
December 19, 2023

TBH if you have to single step your own code to understand how it works you're already in serious trouble.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
waclawek.jan
Super User
December 19, 2023

Why would that example "break", and why would it behave differently at -O0?

JW

PS. For reference, this is the code under the link:

extern void error();

typedef enum { S0 = 3, S1 = 13 } T;

bool f()
{
 static T state = S0;

 switch ( state )
 {
 case S0: state = S1; break;
 case S1: state = S0; break;
 default: error(); break;
 }
// return state == S1;
}
CTapp.1
Senior III
December 20, 2023

It "breaks" because it contains undefined-behaviour (there is no return statement on an exit path from a function having non-void return type. The default is also unreachable, and that adds further to the "unexpected" code generation.

All posts are made in a personal capacity. MISRA C++ Chair, MISRA C WG Member, Director The MISRA Consortium Limited (TMCL)
waclawek.jan
Super User
December 20, 2023

Oh, it's C++, not C.

Language matters, too.

JW

CTapp.1
Senior III
December 20, 2023

Yeah, it can make a difference (and does in that case) - the compilers (and optimisers) are not the same.

For example, the unreachable code has no effect when the example is compiled as C using GCC, but it does when compiling under Clang (the default is optimised out).

 

 

All posts are made in a personal capacity. MISRA C++ Chair, MISRA C WG Member, Director The MISRA Consortium Limited (TMCL)
waclawek.jan
Super User
December 20, 2023

> For example, the unreachable code has no effect when the example is compiled as C using GCC, but it does when compiling under Clang (the default is optimised out).

There is no unreachable code in C, enum specifiers (i.e. the type generated from the enum, not the individual enum symbols/constants) are compatible with int (more precisely, with some of char, signed integer or unsigned integer type, by compiler's choice, C99 6.7.2.2#4), so they can take any value within that type, not just the enumerated values (C99 6.3#2, "Conversion of an operand value to a compatible type causes no change to the value or the representation.")

This is one of the many minor but important differences between C and C++ (the other in this example is treatment of no-return-from-function-with-non-void-return-type).

I wonder what were the conditions under which Clang optimized out the default.

I tried in goldbolt, and indeed, Clang set to C removes that branch with -O2 even with -fno-strict-enums. IMO that's a flaw and I'd like to hear the author's rationale for this.

JW

CTapp.1
Senior III
December 20, 2023

Whilst it is true that an enum object can take any int value, the default is unreachable as the branch to it is infeasible. The compiler can "see" that the only values assigned to state are S0 and S1, and the compiler is allowed (using the "as-if principle) to use that during optimisation.

The only means by which state could hold a different value is by memory corruption, but that is not within the scope of the abstract machine that is used during code generation and it therefore does not have to be considered.

All posts are made in a personal capacity. MISRA C++ Chair, MISRA C WG Member, Director The MISRA Consortium Limited (TMCL)
waclawek.jan
Super User
December 20, 2023

Oh.

Now I see.

I've seen

 

static T state = 50;

 

which would indeed some sort of violation in C++ and perfectly OK in C.

::blushing::

Sorry for the confusion.

Your explanation is then perfectly valid and yes, the default branch can be optimized out, together with the error() call and, consequently, if there's nothing else to call error(), that function can be eliminated too.

In fact, as state is static (i.e. not visible outside f()), and there are no side effects (as it's not volatile), both this variable and thus the whole f() function can be optimized out.

JW