QB64.org Forum
Active Forums => QB64 Discussion => Topic started by: TerryRitchie on March 21, 2020, 12:43:04 pm
-
Lately I've been getting a few anomalous bugs in my code that are very hard to track down and I believe I know the reason.
I've never taken the time zeroize or clear string contents in newly created arrays or variables in BASIC because that seems to have always been done automagically since the days of BASIC 80. However QB64 seems to not be exhibiting the behavior any longer. This seems especially true for variables defined as _BYTE inside and outside of TYPE statements. (I use _BYTE for boolean TRUE(-1) and FALSE(0) flags).
Many times my "bugs" disappear when I take the time to zeroize the arrays and variables I create ... in other words I can't assume any longer that variables and strings will be set to 0 or null when newly created.
Has anyone else run across this behavior? When I have time I'll try to create some code that shows this happening.
-
If you use _MEM commands, they don't clear/initialize memory, but DIM should.
-
Yes, I knew about this behavior with _MEM from the extensive examples and tutorials on the subject you have provided over the years. And yes, I would also assume that DIM would clear/null newly created variables, that why I always DIM every variable I use in code.
It's just that lately routines I create to fire only when a variable is true (non-zero) are triggered without my code setting the variable. Now here's the strange part ... when I print the variable to see what's inside I'm presented with zero. However, for example, an IF statement will treat the variable as being non-zero. If I set the variable to zero manually upon it's creation the IF statement will then see the variable correctly.
It's strange behavior and I can't pin down or predict when/where it will happen in code. I do know though if I zeroize/null all variables before use this behavior seems to disappear in my code. Again, this seems to happen much more often with _BYTE declared variables.
-
No matter what I try to recreate this happening in my code I just can't seem to. The code below executes flawlessly every time. I can't seem to find the secret sauce that is causing this to happen to me.
DIM Testing
(10000) AS TEST
IF Testing
(c
).aType.aByte
THEN PRINT c; Testing
(c
).aType.aByte
IF Testing
(c
).aType.anInteger
THEN PRINT c; Testing
(c
).aType.anInteger
IF Testing
(c
).aType.aLong
THEN PRINT c; Testing
(c
).aType.aLong
IF Testing
(c
).anInteger
THEN PRINT c; Testing
(c
).anInteger
c = c + 1
I'll keep trying to recreate the issue (for my own sanity) and if I find the correct situation that causes this for me I'll post it here.
-
String support was recently added to TYPE. Could it be affecting something?
TYPE whatever
X AS _BYTE
Y AS STRING
Z AS _BYTE
END TYPE
Are you using types like the above and getting Glitches?
-
Type + REDIM _PRESERVE probably good time to zero out new sections. I definitely had code go South with this combo and fixed when zeroed out. But come to think, I don't remember clearing a new section under REDIM _PRESERVE, maybe it was just REDIM with a Type. I don't use Byte too often (Steve says it saves no more room anyway as I recall) so I think the problem was a Type with INTEGER, I was assuming would be 0 but wasn't (before v1.4).
-
The TYPEs I'm creating come in all sizes, from a few variables to as many as 50 or more, all of various declarations from _byte, to string, to long. Many of the TYPEs I create are also embedded with many other TYPE declarations. I'll add strings into the test code and see what happens.
I hoping this is just something anomalous to my coding style or perhaps even my system. However, I ran across this strangeness when creating Widescreen Asteroids but didn't think too much of it. Now it's happening to me again in my latest project and I posted to find out if anyone else had noticed this.
I'm also passing TYPEs between subs/functions so I have a few different scenarios to test and see if I can recreate this.
-
Type + REDIM _PRESERVE probably good time to zero out new sections. I definitely had code go South with this combo and fixed when zeroed out. But come to think, I don't remember clearing a new section under REDIM _PRESERVE, maybe it was just REDIM with a Type.
Ya, that's a good point. I'm using REDIM and _PRESERVE with many of these variables as well.
-
Cross posted I added an edit with more info above.
-
Is that correct? _BYTE uses the same amount of RAM as INTEGER? The only reason I'm using _BYTE is to minimize my program's footprint in RAM. I'll switch everything to INTEGER if this is the case.
-
_BYTE uses a byte. It's _BIT that's troublesome and uses up much more than it lets us think.
-
_BYTE uses a byte. It's _BIT that's troublesome and uses up much more than it lets us think.
Opps! bit, byte sorry.
-
The above results in:
Whereas:
Results in
-
Also, if variable is _BYTE, assigning it a value of 1 (as simply as a = 1), results in this C++ code:
whereas doing the same with a _BIT variable results in this:
if ((*__BIT1_A= 1 )&1){
*__BIT1_A|=-2;
}else{
*__BIT1_A&=1;
}
-
_BYTE uses a byte. It's _BIT that's troublesome and uses up much more than it lets us think.
Thanks for the clarification and code examples.
-
Let's say you have a top secret job as a James Bond super spy. One of your pieces of technology is a notepad on which you can write up to eight passwords on any given page, but afterwards, once you rip that page out, it automatically flies out of the notepad, using nanomachines, and delivers itself to your bosses...
Now, you write one word on a page, rip it out, it flies off...
You write eight words to a page, rip it out, it flies off...
This is basically _BIT in memory.
Bits are stored *INSIDE* bytes (just like you'd store a word on a single James Bond notepad page). You can store 8 bits in one byte (just as you could write 8 words on that page before ripping it off), but those bits are *ALWAYS* stored in bytes...
DIM X AS _BIT is stored in the smallest memory unit available -- a single BYTE. (Honestly speaking, I don't even think QB64 should even allow this type of usage as the overhead is inefficient and there's no single positive that comes from using it.)
...
So when is it useful to use _BIT??
In a large array to save memory.
DIM X AS BIT uses a byte to store its data.
DIM X(1 TO 8) uses a byte to store its data as well. (A byte can hold up to 8 bits.)
So if you need to DIM Foo(8000000) AS BIT, you'll use 1000000 bytes of memory (or disk space), rather than the 8000000 you would need with a BYTE variable type.
*********************
Think of it as similar to:
A notebook is similar to total memory.
A page is the smallest unit you can write on, like a byte.
A word is a partial unit which makes up that page, like a bit makes up portion of a byte.
You can't write a word without scribbling it on a page, just as you can't save a BIT without putting it in a BYTE.
-
A _byte uses a byte, a _bit uses 4 bytes.
-
A _byte uses a byte, a _bit uses 4 bytes.
But an array of 8000000 bytes uses 8000000 bytes. An array of 8000000 bits uses 1000003 bytes. 8 bits compress into one byte, with the descriptor adding a little overhead.
Arrays are the only place where it's advantageous to use bits.