View Issue Details

IDProjectCategoryView StatusLast Update
0000842XdebugUncategorizedpublic2016-12-11 15:23
Reporterdinu Assigned Toderick  
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionduplicate 
Product Version2.2.0 
Fixed in Version2.5.1 
Summary0000842: Can't debug conditional statements without a block
Description
  • If a conditional statement does not have {} for its predicates, I can't debug it (using Zend Studio)
  • If more function calls are invoked in the condition, stepping out of the first does not resume debugging to the next (i.e. there is no way to debug the 2nd function in a condition).

I myself preach the values of good coding practices. However, I find myself stuck with third-party code that I don't want to restyle, mainly because it comes through a CVS that is regularly updated so I'd rather keep the original shape of the code.

Steps To Reproduce

1) Try to get debugger to step on the return statement

if($random)
return 1;
else
return 2;

2) Step into callThis(), then step out; no possibility to step callThat()

if(callThis()||callThat()){
}

TagsNo tags attached.
Operating System
PHP Version5.3.3

Relationships

duplicate of 0001165 closedderick Step Out skips subsequent function calls 
has duplicate 0000895 resolvedderick xdebug never stops on single-line statements 
has duplicate 0001069 resolvedderick Wrong coverage generated for single line if statements 

Activities

rulatir

2012-05-27 20:59

reporter   ~0002192

2) Just to eliminate one possibility: if callThis() returns true then callThat() is not called because the result of the logical OR expression is already known. That's an optimization done by PHP.

dinu

2012-05-27 22:57

reporter   ~0002193

I know, it's pretty standard in any language :) I'm talking about that if the 2 calls are followed.

dinu

2012-05-28 12:00

reporter   ~0002208

More details: cannot set a breakpoint on a conditional predicate without a block: try to set a breakpoint on doThis() or doThat() line

if($cond)
doThis();
else
doThat();

derick

2012-06-01 22:40

administrator   ~0002226

Last edited: 2012-06-01 22:41

For the first case, breakpoints are tricky. Sadly PHP itself doesn't generate the correct line numbers internally. See for example the code:

<pre>
22 function test2($random)
23 {
24 if ($random)
25 test2a();
26 else
27 test2b();
</pre>

Which in PHP turns into:

<pre>
line # * op fetch ext return operands

22 0 > EXT_NOP
1 RECV !0
25 2 EXT_STMT
3 > JMPZ !0, ->8
4 > EXT_FCALL_BEGIN
5 DO_FCALL 0 'test2a'
6 EXT_FCALL_END
7 > JMP ->11
27 8 > EXT_FCALL_BEGIN
9 DO_FCALL 0 'test2b'
10 EXT_FCALL_END
28 11 > EXT_STMT
12 > RETURN null
</pre>

as you can see, there is no line 24 or 26. One of the PHP folks is looking at fixing this, but this is currently not something I can address in Xdebug. Even more annoying, the case for "false" also hits line 25 due to PHP weirdness.

I will now have a look at the second case.

dinu

2012-06-02 04:08

reporter   ~0002227

Last edited: 2012-06-02 09:42

By your example, I should be able to set a breakpoint on 25 or 27. Which I am not; I try to ellaborate a litle on a test case:

<pre>
1 <?php
2 function ret1(){
3 return 1;
4 }
5 function ret2(){
6 return 2;
7 }
8 function dummy1(){
9 echo 'dummy1';
10 }
11 function dummy2(){
12 echo 'dummy2';
13 }
14 if($x)
15 dummy1();
16 else
17 dummy2();
18 if(ret1()&&ret2())
19 dummy1();
20 else
21 dummy2();
</pre>

TS1:

  • set breakpoints on 15,17,19,21
  • expected behavior: stop on 17,19
  • actual behavior: breakpoints don't work, BUT debugger inadvertently stops on line 15, BUT on "step into" command goes into dummy2 at 6

TS2:

  • set breakpoint on 14
  • expected behavior: stop on 14
  • actual behavior: doesn't work as per your explanations

TS3:

  • Step over all the way to 18
  • Step into 18; correctly goes into ret1 on 3
  • Step out of ret1
  • Expected behavior: execution should step into ret2 on 6 (most debuggers do it this way), or _atleast on 19 so I can debug dummy1
  • Actual behavior: all if is skipped; seems to step out not of the function call but of the statement
  • Consequence: the only way to step into a second conditional function or the predicate function is that I have the patience to step all the way through the first conditional function or add incognito breakpoints on function entries

dinu

2012-06-02 04:25

reporter   ~0002228

More discussion over TS3 where I think a definite improvement can be made: most debuggers I'm familiar with interpret debugger commands on conditional statements the following way:

  • Step over if statement

  • Usual: breaks on first instruction of the branch taken

  • XDEBUG: breaks on first instruction after if statement

  • Step into if statement

  • Usual&XDEBUG: step into first function in condition

  • Step out of conditional function

  • Usual: break into the next conditional function then at the first instruction of branch taken

  • XDEBUG: break out of if statement

derick

2012-06-27 21:11

administrator   ~0002299

Marking as "not fixable":

All cases really have the same cause.
In the first bit of TS1 (stop on 17):

It stops on line 15 because of this is where PHP places the if statement:

15 8 EXT_STMT
9 > JMPZ !0, ->1

This is something PHP should have put on line 14, but didn't. The step-into
goes correctly into dummy2 in line 12 (and not 6 like you wrote). This is
because that's what is the next executable line after the if-JMPZ has been
done.

The second case in TS1 (not stopping on line 19) is because PHP
doesn't generate an EXT_STMT, which is required for breakpoint insertions.

TS2 is indeed because PHP simply generates no code on line 14:

11 6 EXT_STMT
7 NOP
15 8 EXT_STMT

TS3 is because PHP doesn't generate an EXT_STMT before the dummy1 call,
as it would do if you would have used braces. Hence it doesn't stop and
goes directly to the next breakable line in a scope higher than where
you were (the ret1 function online 3), wich is the EXT_STMT in line 23.

You fix all of this by just using braces.

derick

2016-12-11 15:23

administrator   ~0003992

This turned out to be a duplicate of 1165, for which I now have cooked up a fix, which will make it into 2.5.1.

Issue History

Date Modified Username Field Change
2012-05-25 03:57 dinu New Issue
2012-05-27 20:59 rulatir Note Added: 0002192
2012-05-27 22:57 dinu Note Added: 0002193
2012-05-28 12:00 dinu Note Added: 0002208
2012-06-01 22:40 derick Note Added: 0002226
2012-06-01 22:40 derick Note Edited: 0002226
2012-06-01 22:41 derick Note Edited: 0002226
2012-06-02 04:08 dinu Note Added: 0002227
2012-06-02 04:25 dinu Note Added: 0002228
2012-06-02 09:42 derick Note Edited: 0002227
2012-06-27 21:11 derick Note Added: 0002299
2012-06-27 21:11 derick Status new => resolved
2012-06-27 21:11 derick Resolution open => not fixable
2012-06-27 21:11 derick Assigned To => derick
2012-10-18 21:53 derick Relationship added has duplicate 0000895
2014-08-14 11:01 derick Relationship added has duplicate 0001069
2016-07-31 12:36 derick Category Usage problems => Usage problems (Crashes)
2016-07-31 12:38 derick Category Usage problems (Crashes) => Usage problems (Wrong Results)
2016-12-11 15:22 derick Status resolved => assigned
2016-12-11 15:23 derick Note Added: 0003992
2016-12-11 15:23 derick Relationship added duplicate of 0001165
2016-12-11 15:23 derick Status assigned => resolved
2016-12-11 15:23 derick Fixed in Version => 2.5.1
2016-12-11 15:23 derick Resolution not fixable => duplicate
2020-03-12 16:35 derick Category Usage problems (Wrong Results) => Variable Display
2020-03-12 16:38 derick Category Variable Display => Uncategorized