NO

Author Topic: Breakpoint in debug mode will stop incorrectly  (Read 6020 times)

neo313

  • Guest
Breakpoint in debug mode will stop incorrectly
« on: March 03, 2014, 03:16:16 AM »
I have discovered a bug related to the optimizer, variable-length arrays and breakpoints.

The code below will work correctly when compiled with no optimizations; it will simply run to the end without activating the breakpoint.

But if you compile with optimizations then you will get a breakpoint trigger in the code, where you absolutely should not. as you never enter the for loop.

Usage: set a breakpoint in the line: int array[size] ;
Code: [Select]
int main( void )
{
int size = 10 ;

        printf("start") ;

for( int i = 0 ; i < 0 ; i++ )
{
printf("woot!") ;
int array[size] ; //SET BREAKPOINT HERE
//printf("add me to the code, to get a unable to set breakpoint warning") ;
}

        printf("end") ;

return 0 ;
}

This might seem only as a gui problem but it isn't. I have discovered this in a larger project where the code terminated unexpectedly when using a loop that never enters and variable-length arrays arrays inside the loop.

If you replace the variable-length array with a normal one or disable optimizations or add the printf statement after the array, you will not trigger the breakpoint.

I'm using win7, 32bit , Pelles v.7.00.355.

::EDITED::
« Last Edit: March 03, 2014, 04:52:26 AM by neo313 »

Offline Bitbeisser

  • Global Moderator
  • Member
  • *****
  • Posts: 772
Re: Breakpoint in debug mode will stop incorrectly
« Reply #1 on: March 03, 2014, 04:35:45 AM »
Your code (in terms of setting the break-point, not referring to the less than useful redeclaration in each of the loops), as it is just a variable declaration, not really executable code. I would not expect any reproducible and predictable behavior in this case to begin with...

Ralf

neo313

  • Guest
Re: Breakpoint in debug mode will stop incorrectly
« Reply #2 on: March 03, 2014, 04:50:42 AM »
Your code (in terms of setting the break-point, not referring to the less than useful redeclaration in each of the loops), as it is just a variable declaration, not really executable code. I would not expect any reproducible and predictable behavior in this case to begin with...

Ralf

I disagree, using gcc with any optimization, and assembly gets produced.  Also pelles, and other compilers, produce an actual executable which runs just fine and even shows in a list of processes in process explorer tools, interesting...

Nevertheless, if that might be the cause, I have added printf() calls to annul your doubts.....
« Last Edit: March 03, 2014, 04:56:54 AM by neo313 »

Offline AlexN

  • Global Moderator
  • Member
  • *****
  • Posts: 394
    • Alex's Link Sammlung
Re: Breakpoint in debug mode will stop incorrectly
« Reply #3 on: March 03, 2014, 08:13:27 AM »
Perhaps the optimizer sees in your code that it never will be entered and remove the complete section and so you will not be able to set a breakpoint. A static array will be created at the top of the function, that could be the reson why you can set a breakpoint to this. ;)
best regards
 Alex ;)

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Breakpoint in debug mode will stop incorrectly
« Reply #4 on: March 03, 2014, 10:06:45 AM »
PellesC optimizer completely remove the loop code because the for condition "i=0; i<0; i++", with local declaration of 'i' and no modification of such value in the loop body, could be statically evaluated (during compiling phase) as never executed. Moreover in classic for loop the condition is immediatly evaluated before the body execution, so this enforces that having initial condition 'i=0' and immediate test for 'i<0' the for loop body will never be executed.
While is not the case of this sample where it is definitely clear that the loop will never execute, in some other cases this extreme optimization could be anyway arguable. There could be some very rare cases where the loop conditions could be changed inside the loop body or the condition itself could be quite complicated in such a way that is not easily understandable by the static optimizer code. This will induce the reduction of loop code and subsequently errors in the program behaviour.
IMHO this issue could be worth some more discussion.
Maybe this could work:
Code: [Select]
int main( void )
{
int size = 10 ;

        printf("start") ;

for( int volatile i = 0 ; i < 0 ; i++ )
{
printf("woot!") ;
int array[size] ; //SET BREAKPOINT HERE
//printf("add me to the code, to get a unable to set breakpoint warning") ;
}

        printf("end") ;

return 0 ;
}
The use of 'volatile' qualifier should stop some optimization assumplions of the compiler, while allowing to keep optimization on over the current module.

P.S. the 'volatile' qualifier instructs the compiler that the variable that it refers to could be changed outside the current program flow so no assumption about its value should be done. This could be seen as a 'no optimization variable's specific', in plane word disables optimizations 'only' for that variable.
« Last Edit: March 03, 2014, 11:18:30 AM by frankie »
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Offline Bitbeisser

  • Global Moderator
  • Member
  • *****
  • Posts: 772
Re: Breakpoint in debug mode will stop incorrectly
« Reply #5 on: March 04, 2014, 01:35:58 AM »
Your code (in terms of setting the break-point, not referring to the less than useful redeclaration in each of the loops), as it is just a variable declaration, not really executable code. I would not expect any reproducible and predictable behavior in this case to begin with...

Ralf

I disagree, using gcc with any optimization, and assembly gets produced.  Also pelles, and other compilers, produce an actual executable which runs just fine and even shows in a list of processes in process explorer tools, interesting...
You did not understand what I am saying. The line
Code: [Select]
int array[size] ; //SET BREAKPOINT HEREis certainly not producing any code by itself, as it is just a variable declaration, something that will happen in a different place, not exactly at between the printf() lines. As there is no executable code at this line of code you are trying to set the break point at, it just don't know where exactly to place the breakpoint and things are rather random as to what might be happening....

This has absolutely nothing to do that you overall get a working executable, you just don't generate code for the exact line you are trying to set the breakpoint at...

Ralf

neo313

  • Guest
Re: Breakpoint in debug mode will stop incorrectly
« Reply #6 on: March 04, 2014, 03:02:33 AM »
@frankie Declaring volatile did fix the bug in the original problem. Since the loop wasn't going to be used anyway, it isn't that important, but I though it was an interesting problem. I tried to reproduce a test example, but I failed as the codebase is just too large.

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Breakpoint in debug mode will stop incorrectly
« Reply #7 on: March 04, 2014, 11:27:30 AM »
About the problem of breakpoint setting you have to consider two aspects.
If an automatic variable declaration happens at start of a function the space on the stack is overall reserved for all module's automatic variables with a single instruction (sub esp,<space in bytes> for 32 bits machine). This is normally considered part of function entry prologue.
In this case as BitBeisser explained no specific instruction is generated and you cannot set a breakpoint on variable declaration.
The situation is different when an automatic variable is declared in the middle of the module, or more generally in a conditional contex that could be optimized away. In this case the variable is automatically allocated extending the stack. To do this the compiler inserts the intructions required for dynamic allocation allowing to break over the variable declaration. You can check this modifyng the code this way:
Code: [Select]
int main( void )
{
int size = 10 ;

        printf("start") ;

for( int volatile i = 0 ; i <= 0 ; i++ )
{
printf("woot!") ;
int array[size] ; //You can set a breakpoint here now, and even debug
array[i]=i; //We *have to* add some op on the array or the optimizer
//will cut off array creation
//printf("add me to the code, to get a unable to set breakpoint warning") ;
}

        printf("end") ;

return 0 ;
}
As already explained in the sample we have to do something on the array or the optimizer will remove it anyway.
The conclusions can be PellesC has a strong optimizer..... :D
I hope someone find this clarification of any interest  :P
« Last Edit: March 04, 2014, 11:31:38 AM by frankie »
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Breakpoint in debug mode will stop incorrectly
« Reply #8 on: March 04, 2014, 11:33:37 AM »
I forgot the essential point:
This is not a bug  8)
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Offline jj2007

  • Member
  • *
  • Posts: 536
Re: Breakpoint in debug mode will stop incorrectly
« Reply #9 on: March 04, 2014, 01:03:29 PM »
...we have to do something on the array or the optimizer will remove it anyway.
The conclusions can be PellesC has a strong optimizer..... :D
I hope someone find this clarification of any interest  :P

It is very interesting, thanks Frankie.

Re strong optimiser: A compiler should replace slow code with fast code (or big code with small code) where possible. If the coder put an instruction there, the compiler should not remove it...

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Breakpoint in debug mode will stop incorrectly
« Reply #10 on: March 04, 2014, 05:39:38 PM »
Thanks JJ
Quote
A compiler should replace slow code with fast code (or big code with small code) where possible. If the coder put an instruction there, the compiler should not remove it...

Not exactly  ;D
Of course the big job of optimization is to use instructions and constructs to speed-up execution, but many codes wrote for different OS's use the standard 'if' instruction to tailor the code. I.e.
Code: [Select]
    if (WIN32)
    {
        Win stuff.....
    }
    else
    {
        Other Os's code...
    }
They use the ability of compiler to recognize statically at compiling time the code that will never execute and remove it (known as 'Dead Code Removal').
This technique is sometimes used instead of classic conditional compiling (#if, #else, #endif) because you can introduce more complex criterias.
Moreover this is a typical application for 'space' optimization.   ;)

Anyway sometimes you can get a surprise (read this).  8)
« Last Edit: March 04, 2014, 05:41:36 PM by frankie »
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

neo313

  • Guest
Re: Breakpoint in debug mode will stop incorrectly
« Reply #11 on: March 04, 2014, 08:05:36 PM »
I forgot the essential point:
This is not a bug  8)

I wish I could reproduce it. My code is linked to threads.h which were also shown to have bugs. At least I have become really efficient at locating the problem. :)
« Last Edit: March 04, 2014, 08:17:42 PM by neo313 »

Offline jj2007

  • Member
  • *
  • Posts: 536
Re: Breakpoint in debug mode will stop incorrectly
« Reply #12 on: March 04, 2014, 09:49:23 PM »
Anyway sometimes you can get a surprise (read this).  8)
Quote
You might ask why I used C’s printf function, rather than C++ std::cout as a way to defeat DCE in the above experiment.  Try it and see.  Both work ok, but the asm file generated by the latter is much bigger, and therefore more difficult to navigate around: 0.7 Mbytes compared with 1.7 Kbytes.
;-)