Power to Build

Home » Misc » PB Gotcha – Integer Max

PB Gotcha – Integer Max

I am working on a problem in our PowerBuilder application that we upgraded to version 12.5 recently. For some reason, client keeps crashing at various points. After sitting with the users for a bit, figured it has something to do with threading and the only thing we do with threads in client is the function Yield(). (we use EAServer for middle tier which uses a lot of threads). After some testing, I did see Yield seems to be having some issues in PB12.5. This was OK in PB 10.2. It’s interesting even to troubleshoot the issue. I will post more on this later.

Now back to the Gotcha: Anyways, while trying to troubleshoot this issue, I decided to write a lot simpler application. Just open a window, Yield and then run a long running function. Instead of the DB (long running) queries we have in the original application, I replaced it with a long running loop.

Code inside a button clicked event

IF ib_show_busy THEN
Open ( w_busy )
w_busy.of_Message ( "Retrieving data. Please wait..." )
Yield()
END IF
long_running_fn()
close(w_busy)

Function: long_running_fn

integer i
integer li_file_num
li_file_num = FileOpen("c:\temp\test.log", LineMode!, Write!, LockWrite!, Replace!)
// 10000 is the loop maximum referred to below
FOR i = 1 to 10000
FileWrite(li_file_num, "i=" + String(i))
NEXT
FileClose(li_file_num)

I ran it with different loop maximum – changing 10000 to 20000 to 40000 and ran. At that point, it was hanging!!!! Do you see any issue here? If you said, it has to do with type of the variable, you guessed it right.

The gotcha is that the integer maximum in PB is the same as for a signed 16-bit integer in good old C, -32,768 to +32,767. They are still sticking to the old 16-bit types. Types mentioned on this PB 7/8 page is still valid!! I kind of knew this, but forgot. What this did to my loop is that at some point it became -ve and started counting backwards. Here is what the output looked like:

i=1


i=32765
i=32766
i=32767
i=32768
i=-32767
i=-32766



i=0
i=1


i=32767
i=-32768
i=-32767
i=-32766


As you can notice, it flipped the sign when it got to 32768!!!! From then on it started counting backward to 0 and repeated through 32767 and beyond all over again, thus causing an infinite loop.

This was interesting. What I learned in 16-bit binary arithmetic was that, when the overflow happens, either the program would error out (see below binary calculator output) or the 16th bit (signed bit) gets set and thus you may get -0, -1 etc as you go past integer maximum (32767). That would have killed the loop immediately after reaching the maximum. But, in PB, it retained the value, only it flipped the sign. This tells me, though integer has 16-bit values, PB is probably storing it in 32-bit storage.(I am running this in PB 12.5 on Windows 7).

2014-08-15 11_37_16-Online calculator_ Binary, inverse and complement codes - Nightly

Just out of curiosity, I changed the loop max to 32-bit max and beyond (for e.g., 2,147,483,648), the loop stopped right after 32767.

If I changed the loop maximum to an integer variable, li_loop_max and set it to a value like 40000, it sets it to a negative value already, so the loop won’t even start.

integer i
integer li_file_num
integer li_loop_max

li_loop_max = 40000
li_file_num = FileOpen("c:\temp\test.log", LineMode!, Write!, LockWrite!, Replace!)

FOR i = 1 to li_loop_max
  FileWrite(li_file_num, "i=" + String(i))
NEXT
FileClose(li_file_num)

I also tried to do this in C (I believe, this happens in Java too, but I didn’t try it recently). Here is a quick little program on Unix and compiled with gcc:

#include <stdio.h>
int main()
{
   int i=0;
   printf("int max = %d\n", INT_MAX);
   for (i=1; i < 10; i++)
   {
      printf("int max + %d = %d\n", i, INT_MAX + i);
   }
}

The output was surprising as well (though C is using 32-bit integer on Unix), the be

int max = 2147483647
int max + 1 = -2147483648
int max + 2 = -2147483647
int max + 3 = -2147483646
int max + 4 = -2147483645
int max + 5 = -2147483644
int max + 6 = -2147483643
int max + 7 = -2147483642
int max + 8 = -2147483641
int max + 9 = -2147483640

But, C compiler (gcc) at least, issued a warning about integer overflow, if I used a variable. PB does none of that. It silently, sets the variable to a -ve value, if the value happens to be larger than the max allowed.

So, if you are using loop variables, beware of the type and max possible values. Try to use Unsigned variables, to maximize the 16-bit usage. Otherwise, use Long type, if you think you may exceed 16-bit maximum.

That’s the gotcha. Come to think of it, there was some old code in our program that kept crashing on the EAServer, with ArrayBoundaryException. There was an innocent loop setting some array values. There is no way, that should get Array Boundary Exception, unless the variable somehow became 0 or something. After analyzing the loop, realized it may be because of the above behavior of integer variable in a loop. There was a bug that caused the values to go beyond int max, but that’s beside the point!!!


2 Comments

  1. Anonymous says:

    Change your “int” to “long”.

    • SamV says:

      Thanks for visiting my blog. Of course that’s what I found out and corrected. But this post was to showcase what happens, if you didn’t. Sometimes, we think the programs will be short lived and outlive our expectation and run into such issues.

      The lesson is to always, anticipate bigger data values for your fields/variables.

Comments, please?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: