Bug? No Null errors while debuging

alcaraz73

Member
If you are in a step by step debug, the "Attempt to invoke virtual method 'boolean java.lang.Object.equals(java.lang.Object)' on a null object reference" error is not fired.

Example:
    Try
        Dim testmap As Map
        testmap.Initialize
        
        'A breakpoint here
        If testmap.Get("notexist") = "B" Then
            ToastMessageShow("Never", True)
        End If
        
        ToastMessageShow("No Catch", True)
    Catch
        ToastMessageShow(LastException, True)
    End Try

Using the breakpoint and pressing F8 will not generate the exception.


Regards
 

alcaraz73

Member
Thanks Erel,

so maybe is a misconfiguration on my side? Something to check?

Regards
 

Attachments

  • errNull.jpg
    errNull.jpg
    39.7 KB · Views: 55
  • NullTest.zip
    4.7 KB · Views: 62

OliverA

Expert
Licensed User
Longtime User
If testmap.Get("notexist") = "B" Then
This is the culprit. The key "notexist", has no entry and therefore testmap.Get("notexist") returns a Null. Null cannot be on the left-hand side of a comparison.

Solution 1: always put a Map's get on the right side of the comparison
B4X:
If "B" = testmap.Get("notexist") Then
In this case, since "B" is a string, the compiler will cast the right side as a string. With testmap.Get("notexist") returning Null, the cast will change it to a B4X Null string, which is a String with the value "null". Since "B" <> "null", the comparison works as is.

Solution 2: Cast the get to a String
B4X:
If testmap.Get("notexist").As(String) = "B" Then
Here you are telling the compiler explicitly to cast the returned Get value to a String

Solution 2 still can fail. Don't rely on the compiler to do the casting for you or use a casting, since Null, for example, does not cast to Int
B4X:
If 1 = testmap.Get("notexist") Then ' Fails if Get returns Null
B4X:
If 1 = testmap.Get("notexist").As(Int) Then ' Fails if Get returns Null

Solution 3: On way is to use GetDefault and make the default value a value that cannot be
B4X:
If "B" = testmap.GetDefault("notexist", "AValueThatShouldNeverBe") Then
B4X:
If 1 = testmap.Get("notexist", -9999999) Then
Will never fail.

Solution 4: Just test if the key exists first
B4X:
If testmap.ContainsKey("notexist") Then
   If "B" = testmap.Get("notexist") Then ' Note: still putting Get on right side of equality
      'Do your stuff here
   End If
End If
With this code, you can distinguish between the key not existing and the key not being equal to some condition. This code may still fail if whatever you get on the right side cannot be cast to the item on the left side of the equation (in the case above if testmap.Get("notexist") cannot be cast to a String).

Programming is so much fun...

Edit (after the fact): Technically, I did not answer the original question. The debugger at times does have an impact on the execution of the program. This is one of those cases. Also fixed some grammar.
 
Last edited:

alcaraz73

Member
This is the culprit. The key "notexist", has no entry and therefore testmap.Get("notexist") returns a Null. Null cannot be on the left-hand side of a comparison.

Solution 1: always put a Map's get on the right side of the comparison
B4X:
If "B" = testmap.Get("notexist") Then
In this case, since "B" is a string, the compiler will cast the right side as a string. With testmap.Get("notexist") returning Null, the cast will change it to a B4X Null string, which is a String with the value "null". Since "B" <> "null", the comparison works as is.

Solution 2: Cast the get to a String
B4X:
If testmap.Get("notexist").As(String) = "B" Then
Here you are telling the compiler explicitly to cast the returned Get value to a String

Solution 2 still can fail. Don't rely on the compiler to do the casting for you or use a casting, since Null, for example, does not cast to Int
B4X:
If 1 = testmap.Get("notexist") Then ' Fails if Get returns Null
B4X:
If 1 = testmap.Get("notexist").As(Int) Then ' Fails if Get returns Null

Solution 3: On way is to use GetDefault and make the default value a value that cannot be
B4X:
If "B" = testmap.GetDefault("notexist", "AValueThatShouldNeverBe") Then
B4X:
If 1 = testmap.Get("notexist", -9999999) Then
Will never fail.

Solution 4: Just test if the key exists first
B4X:
If testmap.ContainsKey("notexist") Then
   If "B" = testmap.Get("notexist") Then ' Note: still putting Get on right side of equality
      'Do your stuff here
   End If
End If
With this code, you can distinguish between the key not existing and the key not being equal to some condition. This code may still fail if what ever you get on the right side cannot be casted to the item on the left side of the equation (in the case above if testmap.Get("notexist") cannot be casted to a String).

Programming is so much fun...

Thanks Oliver,

actually I used that example trying to fire the exception.

The problem (I think) is that the exception is not fired if you are in a step by step debug (F8). That means that there are different behaviors in debug and deploy environments.

Regards
 

OliverA

Expert
Licensed User
Longtime User
If you are in a step by step debug
I just tested this. You don't even have to step through. Just setting a breakpoint will not trigger the error. So
1) If debugging without breakpoints, the catch block is executed as expected
2) If debugging with breakpoint, the error is not tripped and the catch block is ignored

The error is caught in the Catch block.
Not necessarily. See above.

So it's not the debugger by itself that is making a difference in execution, but the act of setting a breakpoint changes the execution outcome.

Note: (need to step away) Tested with B4J 9.80 (yeah, posting in a B4A forum)
 
Top