Bug? [solved] Same code behaves differently - crazy bug

JanG

Member
Licensed User
Longtime User
Hi,

two semantically identical code blocks produce different c++ code in b4a and lead to different behaviour. And the diffent behaviour is the problem. I want to use the code like block 1, but this doesn't work as expected.

I hope, everyone agrees, that block 1 and block 2 should have exactly the same meaning:

Block 1:
B4X:
For i = 0 To 3
  Store1.SetAtPos(i, Element(i))
Next

Block 2:
B4X:
For i = 0 To 3
  Select i
    Case 0
      Store1.SetAtPos(i, Element(i))
    Case 1
      Store1.SetAtPos(i, Element(i))
    Case 2
      Store1.SetAtPos(i, Element(i))
    Case 3
      Store1.SetAtPos(i, Element(i))
  End Select
Next

SetAtPos is a library function that stores the object reference. Later GetAtPos returns the reference at the given position.

Ending Code:
B4X:
TempElement = Store1.GetAtPos(0)
Log("Tag: ", TempElement.Tag)
Log(".")

TempElement = Store1.GetAtPos(1)
Log("Tag: ", TempElement.Tag)
Log(".")

TempElement = Store1.GetAtPos(2)
Log("Tag: ", TempElement.Tag)
Log(".")

TempElement = Store1.GetAtPos(3)
Log("Tag: ", TempElement.Tag)
Log(".")

But the identically ending block gives 2 different log outputs, depending on using block 1 or block 2.
Output Using Block 1:
B4X:
AppStart
Tag: 3
.
Tag: 3
.
Tag: 3
.
Tag: 3
.
Output Using Block 2:
B4X:
AppStart
Tag: 0
.
Tag: 1
.
Tag: 2
.
Tag: 3
.

That bug is a big problem for my current development, because I can't use my new library reliably. I expect the output from block 2 when using block 1 instead, too.

I appended the full test-project (project and library). The library is a cutout of my current development, only to show the problem.
 

Attachments

  • rStoreRef.zip
    1.1 KB · Views: 316
  • TestStoreRef.zip
    979 bytes · Views: 320

Erel

B4X founder
Staff member
Licensed User
Longtime User
The problem is in your library code. It cannot work.
SetAtPos expects an Object. The compiler must create an Object on the stack which is a temporary object. You should never store pointers to stack objects.
It will fail in both cases if you use it in a larger program.

Correct solution:
[module] Queue list
Or:
[module] Stack collection
Or:
[module] GlobalStore - Global objects storage

For further discussion please start a new thread in the questions forum.
https://www.b4x.com/android/forum/threads/73863/#content
 

JanG

Member
Licensed User
Longtime User
If you point to globals, it should't be a problem. I agree that pointing to objects on the stack is a bad idea :).

But your compiler (to C++) creates nice B4R-Objects that have an internal reference to the c++-object. By using this it was possible to modify my library, that it uses references to globals and now my code does work.

Here the cutout of my modified library:
B4X:
Object* B4RStoreRef::getAtPos(Int pPos) {
  tempObject.data.PointerField = refElement[pPos];
  return((Object*) &tempObject);
}

void B4RStoreRef::setAtPos(Int pPos, Object* pElement) {
  refElement[pPos] = pElement->data.PointerField;
}

The new versions of the full library is on the first posting.
 
Top