gdb stop@simple assignments #compiler optimize

Toggle between -O2 and -O0, which is the default non-optimized compilation.

In my definition, A “simple assignment” is one without using functions. It can get value from another variable or a literal. Simple assignments are optimized away under -O2, so gdb cannot stop on these lines. This applies to break point or step-through.

In particular, if you breakpoint on a simple assignment then “info breakpoint” will show a growing hit count on this breakpoint, but under -O2 gdb would never stop there. -O0 works as expected.

As another illustration, if an if-block contains nothing but simple assignment, then gdb has nowhere to stop inside it and will only stop after the if-block. You won’t know whether you entered it. -O0 works as expected.


OneDefinitionRule is more strict on global variables (which have static duration). You can’t have 2 global variables sharing the same name. Devil is in the details:

As explained in various posts, you declare the same global variable in a header file that’s included in various compilation units, but you allocate storage in exactly one compilation unit. Under a temporary suspension of disbelief, let’s say there are 2 allocated storage for the same global var, how would you update this variable?

With free function f1(), ODR is more relaxed. explains the Lessor ODR vs Greater ODR. My focus today is the Greater ODR therein. The same function can be included via a header file into multiple compilation units and goes into multiple binaries. Two copies of this function are usually identical definitions. If they actually have different definitions, compiler/linker can’t easily notice and are not required to verify, so no build error (!) but you get could strange run time errors.

Java linker is simpler and never cause any problem so I never look into it.

c++non-void function without a return value!

Strictly, undefined behavior not a compiler error. explains the rationale.

However, in practice,

  • For an int function the compiler could return any int value.
  • For functions returning type AA, I don’t know what is returned. Could it be a default-constructed instance of AA?
    • My specific case — I modified a well-behaving function to introduce an exception. I then added a catch-all block without a return value. Actually worked fine. So some instance of AA is actually returned!


linker dislikes(non-generic)function definition in shared header

I used to feel header files are optional so we can make do without them if they get in our ways. This post shows they aren’t optional in any non-trivial c++ project. There is often only one (or few) correct way to structure the header vs implementation files. You can’t make do without them.

Suppose MyHeader.h is included in 2 cpp files and they are linked to create an executable.

A class definition is permitted in MyHeader.h:

class Test89{
void test123(){}

However, if the test123() is a free function, then linker will fail with “multiple definition” of this function when linking the two object files. iles-works-but-not-functions explains the rules

* repeated definition of function (in a shared header) must be inlined * repeated class definition (in a shared header) is permitted for a valid reason (sizing…). Since programmers could not only declare but define a member function in such a class, in a header, the compiler silently treats such member functions as inline

delete base class ptr,with non-virtual dtor#based dtor runs!

This correct code produces ” ~B ~A” i.e. reverse construction sequence. But what if “virtual” removed?

I said it’s undefined behavior, but what if we know it does do something?

I correctly predicted “~A”, tested in minGw.

class A{
public: virtual ~A(){ cout<<" ~ A"<<endl; }
class B: public A{
public: ~B(){ cout<<" ~ B "; }
int main(){
A * p = new B;
delete p;