Author Topic: Question about DIMing user-defined types  (Read 3110 times)

0 Members and 1 Guest are viewing this topic.

Offline jakeh0916

  • Newbie
  • Posts: 9
    • View Profile
Question about DIMing user-defined types
« on: March 03, 2021, 05:45:36 pm »
Hi everybody, I had a quick question about DIM and how it works with user-defined types.

Say I create a type for a 3d point,
Code: QB64: [Select]
  1. Type vec3
  2.    x as double
  3.    y as double
  4.    z as double
  5.  

When I DIM something of this type, can I safely assume that it will always DIM the type with defaulted values (x = 0, y = 0, z = 0), or is there a chance that the program will reuse some bits of memory, and end up with my x, y or z variables equaling something other than 0? The superstitious part of me wants to do something like this to ensure that my variables always get set up properly:

Code: QB64: [Select]
  1. ' Set up some "default" variable at the beginning of the script...
  2. Dim Shared vec3_default as vec3
  3. vec3_default.x = 0
  4. vec3_default.y = 0
  5. vec3_default.z = 0
  6.  
  7. ' And use that default variable to initialize any DIMed variable
  8. Dim someRandomPoint as vec3
  9. someRandomPoint = vec3_default
  10.  

So my question is, in general: when you DIM a user defined type, does the program make sure to reset all of the bits and whatnot in memory, or does it just dimension the variable without looking at whether there was already some stuff there in memory? My thinking is that it will actually reset the memory when it DIMs any variable, but I wasn't quite sure.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Question about DIMing user-defined types
« Reply #1 on: March 03, 2021, 06:18:25 pm »
No it's not safe to assume UDT's will start at zero or "" best to assign them to 0 if not some other initial value.

This might of been fixed but I don't remember when.

I recently did programMap UDT in v1.4 and was getting crazy stuff happening until I remembered to 0 out all values at the start.

Code: QB64: [Select]
  1.     UBPM = UBound(Program$)
  2.     ReDim ProgramMap(1 To UBPM) As ProgramLine
  3.     For i = 1 To UBPM 'oh yeah ============================ Zero Out Type array!!!!!!!
  4.         ProgramMap(i).LoopLevel = 0: ProgramMap(i).IFLevel = 0: ProgramMap(i).GoToT = 0
  5.         ProgramMap(i).GoToAlt = 0: ProgramMap(i).Cmd = "": ProgramMap(i).ArgLine = ""
  6.         k = Len(Program$(i))
  7.  
  8.  

Now I am remembering ReDim _Preserve as well, the new parts might have to be 0'd also though I don't recall any incidents from that.
« Last Edit: March 03, 2021, 06:27:47 pm by bplus »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Question about DIMing user-defined types
« Reply #2 on: March 03, 2021, 07:17:19 pm »
Hi Jakeh0916

I'm used to initialize my variable, both predefinied kind of variable both UDT variable. But I can affirm that I have had no issue about a casual wrong value into a variable DIMmed.

Wiki spent no a word about this your issue https://www.qb64.org/wiki/DIM at page of DIM keyword.
Just a tip to you, here you can find 2 different ways to get initialization to 0 or ""
CLEAR after declaring all the variables and arrays http://www.qb64.org/wiki/CLEAR
here a demo
Code: QB64: [Select]
  1. Type point3D
  2.     X As Long
  3.     Y As Long
  4.     Z As Long
  5.  
  6. Type D2point
  7.     As Long X, Y, Color
  8.  
  9. Dim A As Integer, B(1 To 10) As point3D, c As D2point
  10. Print c.X, c.Y, c.Color
  11. For d = 1 To 10 Step 1
  12.     Print B(d).X, B(d).Y, B(d).Z
or for single dynamic array you can use ERASE https://www.qb64.org/wiki/ERASE.
Good Coding
Programming isn't difficult, only it's  consuming time and coffee

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Question about DIMing user-defined types
« Reply #3 on: March 03, 2021, 07:28:16 pm »
You could do this as well:

Code: QB64: [Select]
  1.  
  2.     Function ZeroMemory%& Alias SecureZeroMemory (ByVal ptr As _Offset, Byval cnt As _Unsigned Integer)
  3.  
  4. Type test
  5.     As Long data1, data2
  6.  
  7. Dim As test test
  8.  
  9. a = ZeroMemory(_Offset(test), Len(test))
Shuwatch!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Question about DIMing user-defined types
« Reply #4 on: March 03, 2021, 08:45:43 pm »
I am not finding non zero's in v 1.5 trying a number of things that might throw it off.

Code: QB64: [Select]
  1. Type vec3
  2.     x As String
  3.     y As String
  4.     z As String
  5.  
  6. ReDim Shared V3(1 To 100) As vec3
  7. ReDim a(1 To 1000000) As Double
  8.  
  9. For i = 1 To 1000000
  10.     a(i) = Rnd
  11. ReDim a(1 To 1)
  12. makeV3Bigger
  13. For i = 1 To 1000000
  14.     Print i, V3(i).x, V3(i).y, V3(i).z
  15.     If Val(V3(i).x) <> 0 Or Val(V3(i).y) <> 0 Or Val(V3(i).z) <> 0 Then
  16.         Beep
  17.         Print "Found non 0 in line above.  Zzz... press any"
  18.         Sleep
  19.     End If
  20.  
  21.  
  22. Sub makeV3Bigger
  23.     For i = 1 To 1000000
  24.         Print "MakeBigger:"; i
  25.         If UBound(V3) < i Then ' of course we do this at every step
  26.             ReDim _Preserve V3(1 To i) As vec3
  27.         End If
  28.     Next
  29.  

Update: this code didn't generate any in v1.3 or v1.4 either so... a watched pot never boils.
« Last Edit: March 03, 2021, 08:51:55 pm by bplus »

Offline luke

  • Administrator
  • Seasoned Forum Regular
  • Posts: 324
    • View Profile
Re: Question about DIMing user-defined types
« Reply #5 on: March 04, 2021, 03:05:04 am »
TYPE elements are always* initialised to 0. This includes when REDIMming an array of them.

* There's an elusive bug that sometimes causes elements to not be initialised to 0, but this is only for TYPEs that have an AS STRING element.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Question about DIMing user-defined types
« Reply #6 on: March 04, 2021, 07:46:33 pm »
The "Nessie" of QB64 is now captured on film! ( v1.5 )

I have replicated conditions that gave me recent sighting of non zero initializing of Long type variables in UDT:
Code: QB64: [Select]
  1. Screen _NewImage(1024, 672, 32)
  2. _Delay .25
  3.  
  4. Type PgMap ' duplicating  the situation where I got stuff in non zeroed long values in new UDT array
  5.     S1 As String
  6.     S2 As String
  7.     L1 As Long
  8.     L2 As Long
  9.     L3 As Long
  10.     L4 As Long
  11.  
  12. ReDim Shared P$(1 To 200) ' i was working with another string array
  13. ReDim Shared UBPM As Long, PM(1 To 1) As PgMap
  14. For i = 1 To 200 'put stuff in p()
  15.     'Print "Building p() array line:"; i
  16.     If Rnd < .5 Then
  17.         rstop = Int(Rnd * 10) + 1
  18.         b$ = ""
  19.         For j = 1 To rstop
  20.             b$ = b$ + Chr$(Int(Rnd * 26) + 65)
  21.         Next
  22.         P$(i) = b$
  23.     End If
  24. Parser
  25. ' now see if anything unusual in pm  specially the L values
  26. For i = 1 To UBPM
  27.     Print i, PM(i).S1, PM(i).S2, PM(i).L1, PM(i).L2, PM(i).L3, PM(i).L4
  28.     If i Mod 20 = 0 Then
  29.         Print "Zzz... press any"
  30.         Sleep
  31.     End If
  32.  
  33. Sub Parser
  34.  
  35.     UBPM = UBound(p$)
  36.     ReDim PM(1 To UBPM) As PgMap
  37.     For i = 1 To UBPM
  38.         'Print "First pass building PM() the UDT not zero'd out line:"; i
  39.         If P$(i) <> "" Then
  40.             PM(i).S1 = Left$(P$(i), 2)
  41.             PM(i).S2 = Mid$(P$(i), 3)
  42.         End If
  43.     Next
  44.     For i = 1 To UBPM
  45.         Print "2nd pass building PM() with UDT not zero'd out line:"; i
  46.         If Left$(PM(i).S1, 1) = "A" Then ' assuming .L1, .L2... are 0 so adding 1 first time makes it 1...
  47.             PM(i).L1 = 1
  48.         ElseIf Left$(PM(i).S1, 1) = "B" Then
  49.             PM(i).L2 = 1
  50.         ElseIf Left$(PM(i).S1, 1) = "C" Then
  51.             PM(i).L3 = 1
  52.         ElseIf Left$(PM(i).S1, 1) = "D" Then
  53.             PM(i).L4 = 1
  54.         End If
  55.     Next
  56.  
  57.  
  58.  

  [ You are not allowed to view this attachment ]  

The items in each of the 4 columns on right represent Long Type and can at MOST have 1 in either of 4 columns,
instead you can see all kinds of crazy data. Run again, and at first it may appear correctly with all 0's or 1 but page down (press key through SLEEPs and find a line or 2 of outrageous number (not 0 or 1).

2nd Run and Nessie looks like she's gone but no... page through all 200 lines...
  [ You are not allowed to view this attachment ]  

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Question about DIMing user-defined types
« Reply #7 on: March 04, 2021, 09:02:26 pm »
TYPE elements are always* initialised to 0. This includes when REDIMming an array of them.

* There's an elusive bug that sometimes causes elements to not be initialised to 0, but this is only for TYPEs that have an AS STRING element.

Not to rain on your parade, but Luke already mentioned how to generate this glitch, above.  You have to have an AS STRING element in your UDT....

Which is just another reason why I personally just consider variable-length strings as being experimental still, and they’re something I try to avoid in my TYPEs.  Now, once we can somehow GET/PUT types with variable-strings in them, I’ll probably use them like a fat kid uses candy, regardless of other hoops which I might need to watch for (like non-initialized arrays).  ;D
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Question about DIMing user-defined types
« Reply #8 on: March 05, 2021, 12:30:23 am »
Yeah but don't you find it curious, most curious, how the introduction variable length strings corrupts the integrity of Longs of other numeric type?

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Question about DIMing user-defined types
« Reply #9 on: March 05, 2021, 12:49:05 am »
Yeah but don't you find it curious, most curious, how the introduction variable length strings corrupts the integrity of Longs of other numeric type?

Not really.  If I had to guess, the internal process is probably using some process like:

Find first element memory address.
Count total space of type.
Multiply space * array size.
Mem fill address, total size, 0’s...

Now, with the first element being a variable-length string, that’s NOT where the array starts; it’s a pointer to where that string is stored in memory.  That could be the issue.

Or...   total type size could be off.  2 * Variable STRING + 3 * LONG...  What is the LEN(TYPE)?  12?  0?  Something else?   That can affect the mem fill...

I’d say it’s  basically something related to the above that is causing the issue.  The easiest way to initialize a variable/array to zero is just memfill m, m.offset, m.size, 0 — but how do you calculate those fill values?

When variable length strings are in use, you almost have to have a loop similar to:
FOR I = lbound TO ubound
   t$(I) = “”
NEXT

Since TYPEs never handled variable lengths until recently, it makes sense that their fill routine went the quick and simple route of memfill, rather than a slower loop fill structure.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!