Android Question Very strange loss of bitmap dimensioning

In the 12 years that I have been using B4A I have never experience this strange error before: I have dimensioned a bitmap in the Globals with "Dim Bitmap1 as bitmap".
Everything in my app works fine apart from with three specific sub routines that use this bitmap object, during which B4A suddenly reports that the bitmap has become Null. The app then crashes with the famous "...null reference object" java error. As a work around I had to add this routine in the effected Sub:
B4X:
If Bitmap1 = Null then
  Dim Bitmap1 as bitmap
end if
I have no explanation. What causes this?
 

emexes

Expert
Licensed User
THIS IS ONLY A GUESS but it feels like it's been garbage-collected. But if you have a Global referencing it, then that should "protect" it.

You've probably already done this, but just in case:

I would try to reproduce the problem on the development computer, see if I could pinpoint when (and where) Bitmap1 is set to Null with eg:

B4X:
If Bitmap1 = Null Then
    Log("Dude, where's my Bitmap1 ???")
    Dim Bitmap1 As Bitmap
Else
    Log("Bitmap1 ok")
End If

and maybe a few of this line peppered about the code:

B4X:
If Bitmap1 = Null Then Log("Dude, where's my Bitmap1 ???")

or maybe call it as a Sub to avoid repetitive code code. ?
 
Upvote 0
Thanks. My point is that this should never happen. Once an object is declared under Globals it should remain declared.
I don't think it has anything to do with the garbage collector. The problem can be consistently reproduced.
 
Upvote 0

Brian Dean

Well-Known Member
Licensed User
Longtime User
[Edit : Disregard this post. It is not correct - except possibly the final sentence. BRD]

We should get something straight here.
As a work around I had to add this routine in the affected Sub :
This is not really a "work-around". If you declared a variable (Bitmap1) in Globals then it was important that that variable was recognised throughout the activity. If you subsequently declare Bitmap1 in a subroutine then this does not fix the problem that the globally declared Bitmap1 was not recognised in that subroutine; you are declaring a new variable that has no link to the globally declared variable. If your program still works then it illustrates that the original global declaration was not, in this particular instance, a necessary one.
I have no explanation. What causes this?
My only explanation is that you are not doing what you think that you are doing. Without more code to inspect it is difficult to say more.
 
Last edited:
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
What goes into the bitmap?
If it loaded from a file ensure the read is not returning a null ( file not found etc)
 
Upvote 0
What goes into the bitmap?
If it loaded from a file ensure the read is not returning a null ( file not found etc)
But surely that should not destroy the bitmap dimensioning under Globals? By the way, this Bitmap1
We should get something straight here.

This is not really a "work-around". If you declared a variable (Bitmap1) in Globals then it was important that that variable was recognised throughout the activity. If you subsequently declare Bitmap1 in a subroutine then this does not fix the problem that the globally declared Bitmap1 was not recognised in that subroutine; you are declaring a new variable that has no link to the globally declared variable. If your program still works then it illustrates that the original global declaration was not, in this particular instance, a necessary one.

My only explanation is that you are not doing what you think that you are doing. Without more code to inspect it is difficult to say more.

is successfully used all over the place in my huge app. It is only in 2 places where it is deemed to be Null.
 
Upvote 0
I hear what you say, but the Globally Dimmed Bitmap1 still does its task in a huge number (a couple of hundred places!) in other subs in my extensive app.
It's only in two subs that it crashes with the Null error.
 
Upvote 0

RichardN

Well-Known Member
Licensed User
Longtime User
Surely it is simple....

1. You can't refer to a variable that requires initialisation... before you have initialised it.... and ,
2. You can't have a Global variable and a Local variable with the same name. That is bound to confuse the **** out of the compiler.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
1. It has nothing to do with the GC.
2. A local variable can never have the same name as a global variable. It will point to the global variable.

There isn't enough information here but the two possible causes are:
Globals, unlike Process_Globals, have the same scope as the activity. This means that if the activity was closed and later recreated the globals need to be assigned again.

Or:

Somewhere you assigned null to the global variable (maybe mistakenly assuming that it is a local variable).

BTW, switching to B4XPages will make things simpler as you no longer need to manage the activity life cycle.
 
Upvote 0

Brian Dean

Well-Known Member
Licensed User
Longtime User
2. A local variable can never have the same name as a global variable. It will point to the global variable.
I might be misreading that sentence, but why doesn't this example show that it is not true? Are global and local variables not what I think they are?
B4X:
Sub Process_Globals
    Private MainForm As Form
    Private Button1 As B4XView
   
    Private number As Int                              ' This is a global variable
   
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1")
    MainForm.Show
End Sub

Sub Button1_Click
    number = 11
    Log("global 'number' in click event = " & number)
    subroutine
End Sub

Sub subroutine
    Dim number As Int                             ' This is a local variable
    number = 22
    Log("local 'number' in subroutine = " & number)  
End Sub

When run it produces this log output . . .
global 'number' in click event = 11
local 'number' in subroutine = 22
 
Last edited:
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
Line 22 does nothing more than set number to 0. 'number' is already declared as global.
There are situations where you would Dim a global variable again.
One is when you want to re'dim'ension an Array or set its values to defaults.
B4X:
Private Sub test
    Root = Root1
    testNumber        '11
    Dim number As Int
    testNumber        '0
    number = 22
    testNumber        '22
End Sub

Private Sub testNumber
    Log(number)
End Sub
 
Last edited:
Upvote 0
1. It has nothing to do with the GC.
2. A local variable can never have the same name as a global variable. It will point to the global variable.

There isn't enough information here but the two possible causes are:
Globals, unlike Process_Globals, have the same scope as the activity. This means that if the activity was closed and later recreated the globals need to be assigned again.

Or:

Somewhere you assigned null to the global variable (maybe mistakenly assuming that it is a local variable).

BTW, switching to B4XPages will make things simpler as you no longer need to manage the activity life cycle.
Thank you for your reply. However, none of these cases apply, and I think it must be a bug in B4A:
1. I do not nullify the bitmap anywhere, I checked it!
2. Also the Activity is always active and never pauses nor resumes and thus needs no lifecycle solutions.
3. I do not re-dim the bitmap anywhere in any subs (easy to check by searching for "Dim Bitmap1").
4. All png's and jpg's that my app loads into Bitmap1 are valid and present picture files in the DirAssets folder.

My workaround does exactly what I want it to do: revive the global Bitmap1! With the code in #1 all problems are solved. The app never crashes anywhere else, although the global Bitmap1 is re-used hundreds of times in the app.

PS: I never felt the need and also am too old to learn new tricks like B4Xpages (nearly 70 years old...) and am perfectly happy developing without it, sorry!
I tried B4X version-12 but ran into about a 100 problems when trying to convert/upgrade my main app (which I have been working on since 2013), so I gave up.
 
Upvote 0

Brian Dean

Well-Known Member
Licensed User
Longtime User
Line 22 does nothing more than set number to 0.
Well - I have learned something today. I cannot believe that I have used B4X for ten years without discovering this. Maybe it was different in some other language that I used in the past.

By the way, I realise now that I left out the important step in my "test example" that would have saved me this embarrassment, but that is just another lesson in life - you don't look for what you don't expect to find.
 
Last edited:
Upvote 0

Addo

Well-Known Member
Licensed User
Longtime User
Why? Use the IsInitialized property.
B4X:
    If Bitmap1.IsInitialized = False Then
        Dim Bitmap1 As Bitmap
    End If
As Alexander stated why not using IsInitialized it will be a good practice to check if the object you are using is always Initialized! You can simply create a small function for that by passing your bitmap object as a parameter then do your checks inside it so you can later safely use it.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Thank you for your reply. However, none of these cases apply, and I think it must be a bug in B4A:
1. I do not nullify the bitmap anywhere, I checked it!
2. Also the Activity is always active and never pauses nor resumes and thus needs no lifecycle solutions.
3. I do not re-dim the bitmap anywhere in any subs (easy to check by searching for "Dim Bitmap1").
4. All png's and jpg's that my app loads into Bitmap1 are valid and present picture files in the DirAssets folder.

My workaround does exactly what I want it to do: revive the global Bitmap1! With the code in #1 all problems are solved. The app never crashes anywhere else, although the global Bitmap1 is re-used hundreds of times in the app.

PS: I never felt the need and also am too old to learn new tricks like B4Xpages (nearly 70 years old...) and am perfectly happy developing without it, sorry!
I tried B4X version-12 but ran into about a 100 problems when trying to convert/upgrade my main app (which I have been working on since 2013), so I gave up.
I'm 100% that there is no bug that causes global variables to become null. There would have been endless reports about such issue if it was the case.
Anyway, without a way to reproduce it I cannot say more.
 
Upvote 0
Top