Author Topic: Volatility of variables...  (Read 1656 times)

0 Members and 1 Guest are viewing this topic.

Brian Alvarez

  • Hero Member
  • *****
  • Posts: 653
    • PluriBASIC
Volatility of variables...
« on: August 16, 2019, 08:59:13 PM »
 Charles, i noticed strings are destroyed even if they were created with the AT switch:

Code: [Select]
string s at hBuffers
 I think the volatility of strings should be removed for strings created AT a custom address.

 I havent tested if this behavior also occurs with other data types, but it also occurs with strings created with the ptr switch when they are returned as the result of a function:

Code: [Select]
        function strng(int hBuffer) as string
            string ptr dt : @dt = hBuffer
            return dt
        end function

Brian Alvarez

  • Hero Member
  • *****
  • Posts: 653
    • PluriBASIC
Re: Volatility of variables...
« Reply #1 on: August 16, 2019, 09:34:36 PM »
Hmm this is weird... i think it is not the volatility of the strings (garbage collector)... it appears to be some kind of internal optimization that backfires...
This "property set" method of the class fails to set the string value (it dissapears):

Code: [Select]
        function s(int d1, dtype v)
            dtype dt at (hBuffer + this.m(d1))           
            dt = v
        end function

But this works (it correctly sets the value of the string):

Code: [Select]
        function s(int d1, dtype v)
            dtype dt at (hBuffer + this.m(d1))           
            dt = v
            return dt           
        end function

Apparently if it is not used... it is not set...

Brian Alvarez

  • Hero Member
  • *****
  • Posts: 653
    • PluriBASIC
Re: Volatility of variables...
« Reply #2 on: August 16, 2019, 09:43:23 PM »
Maybe i am too tired. I dont trust my eyes anymore. Ill get back to it tomorrow. Probably it is my fault somehow.

Code: [Select]
class tsc
 
    int Offset = 10
 
    function w(sys hm, string v)
        string dt at (hm + Offset)
        dt = v
        return dt            ' COMMENT THIS LINE OUT AND IT FAILS.
    end function
   
    function r(sys hm) as string
        string dt at (hm + Offset)
        return dt
    end function   
end class

sys hm = getmemory(100)
new tsc tc()

tc.w(hm) = "Hello World"

print tc.r(hm) + chr(13, 10)

freememory(hm)
« Last Edit: August 16, 2019, 10:01:05 PM by Brian Alvarez »

Brian Alvarez

  • Hero Member
  • *****
  • Posts: 653
    • PluriBASIC
Re: Volatility of variables...
« Reply #3 on: August 16, 2019, 10:37:09 PM »
One last post before bed time... Something anormal is messing with my code:

Code: [Select]
class tsc 
    sys ph
    int Offset
   
    function constructor()
        Offset = 10
    end function
 
    function m(sys hm) as long
        return Offset
    end function
   
    function w(sys hm, string v)
        ph = hm
        string dt at (hm + this.m(hm))
        dt = v
        return dt  ' REMARK THIS AND IT FAILS.
    end function
   
    function r(sys hm) as string
        print "*execution does not end here*" + chr(13, 10)
        print "*But I should not be returned*" + chr(13, 10)
        string dt at (hm + Offset)
        return ">>" + rtrim(dt) + "<<"
    end function
           
end class

  sys hm = getmemory(100)
new tsc tc()

  tc.w(hm) = "Hello World"

  print "This is returned: " + tc.r(hm) + chr(13, 10)

  freememory(hm)

Output:
Code: [Select]
*execution does not end here*
*But I should not be returned*
this is returned: >>*But I should not be returned*<<

Brian Alvarez

  • Hero Member
  • *****
  • Posts: 653
    • PluriBASIC
Re: Volatility of variables...
« Reply #4 on: August 16, 2019, 10:47:30 PM »
Definately something needs fixing. Check this out:

Code: [Select]
class tsc 
    int Offset
   
    function constructor()
        Offset = 10
    end function
 
    function m(sys hm) as long
        return Offset
    end function
   
    function w(sys hm, string v)
        string dt at (hm + this.m(hm))
        dt = v
        return dt  ' REMARK THIS AND IT FAILS.
    end function
   
    function r(sys hm) as string
        string dt1 at (hm + Offset)
        return ltrim(">>" + dt1 + "<<")
    end function
           
end class

sys hm = getmemory(100)
new tsc tc()

  tc.w(hm) = "  Why do these get stored?  "

  print "this is returned: " + tc.r(hm) + chr(13, 10)
  print "this is returned: " + tc.r(hm) + chr(13, 10)
  print "this is returned: " + tc.r(hm) + chr(13, 10)
  print "this is returned: " + tc.r(hm) + chr(13, 10)
  print "this is returned: " + tc.r(hm) + chr(13, 10)
  print "this is returned: " + tc.r(hm) + chr(13, 10)

  freememory(hm)

Output:
Code: [Select]
this is returned: >>  Why do these get stored?  <<
this is returned: >>>>  Why do these get stored?  <<<<
this is returned: >>>>>>  Why do these get stored?  <<<<<<
this is returned: >>>>>>>>  Why do these get stored?  <<<<<<<<
this is returned: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<
this is returned: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<

Aurel

  • Guest
Re: Volatility of variables...
« Reply #5 on: August 17, 2019, 05:20:22 AM »
I am receiving error on line 26
that tc is not defined...   and is NOT !

but what happened with OxIDE ?
when i try to add  tc[] then oxIDE constantly jump to tab with number 26
so in OxIDE is some strange error ...
OxIDE not recognize symbols  [ ] and jumps like I use TAB  ???
.... Charles you need to fix this.
« Last Edit: August 17, 2019, 05:42:56 AM by Aurel »

Aurel

  • Guest
Re: Volatility of variables...
« Reply #6 on: August 17, 2019, 05:32:49 AM »
well it looks that offset is a keyword

so i changed var offset to ofset ,,with one f

and program compile and run.
this time i used AurelEdit_037 where I can type []

then after i click close program crush??

Charles Pegge

  • Admin Support Member
  • *****
  • Posts: 4417
    • Oxygen Basic
Re: Volatility of variables...
« Reply #7 on: August 17, 2019, 06:57:47 AM »
Hi Brian,

For objects which have string members, it is best to use bstring and wbstring, and implement a destructor to free them. Then you have full control over string management.

When creating arrays of strings or UDTs with string members, whose content is to be altered in another procedure, it is necessary to first initialize with something, usually "". This ensures that each new string is registered on the correct garbage-collection list. There is one list for globals/statics and separate local lists for each procedure.
« Last Edit: August 17, 2019, 07:14:59 AM by Charles Pegge »

Brian Alvarez

  • Hero Member
  • *****
  • Posts: 653
    • PluriBASIC
Re: Volatility of variables...
« Reply #8 on: August 17, 2019, 10:24:34 AM »
Hello Charles, unfortunately, none of this solutions are practical in this case.

 As you may have already figured, i am implementing the AT option for arrays.
It works perfectly fine with UDT's and integer arrays, but presents this problem
when working with string, wstring and some floating point types.

 In the case os STRING, Using bstring is not an option, because i need to think
about the programmer getting the array element VARPTR in order to pass the array
element BYREF to the modules. Granted, yes, i tested yesterday that it indeed solves
the issue, but If i return the pointer to a bstring when the code expects a pointer to a
string, something will fail. Program crashes.

 About initializing the array with = "",  in the example i set it up with = "Hello world",
does it need to be exactly a = ""? Because I cannot initialize an array like this when
passing the address with AT... I am supposed to rely on whatever is already there,
initializing the array would erase the initial contents, rendering ths feature useless.

 Thanks for the suggestions though! It shows i wasn't too lost while testing, but what
about the function returining the contents of what print outputs? do you mean that
is normal? when it concatenates and stores what is supposed to be just a temporary
concatenation for outputing the value of r() is normal?

 This is the final step for having perfect arrays. I found another solution which is a horrible
hack, but I would prefer to have an "official patch". :) :D

Brian Alvarez

  • Hero Member
  • *****
  • Posts: 653
    • PluriBASIC
Re: Volatility of variables...
« Reply #9 on: August 17, 2019, 10:56:59 AM »
This ensures that each new string is registered on the correct garbage-collection list.

 This is golden knowledge Charles! just one thing... when setting a value for a PTR string or a string declared with AT... it should not be registered in any garbage-collection list.

Charles Pegge

  • Admin Support Member
  • *****
  • Posts: 4417
    • Oxygen Basic
Re: Volatility of variables...
« Reply #10 on: August 17, 2019, 04:29:44 PM »
o2 strings have 2 levels of indirection. The first is a pointer to  a GC list entry. This entry contains its current bstring which, in turn, points to the string content.

If an array  of strings is already initialized then you can create pointers to it, and safely pass the array to procedures which alter the strings.

What you cannot do is create an array of strings in a function, assign local content to them, and return the array. The initialized array must be set up before calling any function which may alter the strings in the array.


Brian Alvarez

  • Hero Member
  • *****
  • Posts: 653
    • PluriBASIC
Re: Volatility of variables...
« Reply #11 on: August 17, 2019, 08:44:33 PM »
What you cannot do is create an array of strings in a function, assign local content to them, and return the array...

 Apparently i can. And i did:

Code: [Select]
class tsc 
    int Offset
    string ptr dt
   
    function constructor()
        Offset = 0
    end function
   
    function destructor()
        ' How do i destroy strings here?       
    end function   
 
    function m(sys hm) as long
        return Offset
    end function
   
    function w(sys hm, string v)
        @dt = (hm + this.m(hm))
        dt = v
    end function
   
    function r(sys hm) as string
        @dt = (hm + this.m(hm))
        return dt
    end function
           
end class

sys hm = getmemory(100)

new tsc tc()

tc.w(hm) = "This works fine."

print "Returned: " + tc.r(hm) + chr(13, 10)
print "Returned: " + tc.r(hm) + chr(13, 10)
print "Returned: " + tc.r(hm) + chr(13, 10)
print "Returned: " + tc.r(hm) + chr(13, 10)
print "Returned: " + tc.r(hm) + chr(13, 10)

freememory(hm)

 It looks like Oxygen has no issue whatsoever as long as (as i said) the variable doesn't
go out of scope and into the garbage collector (hence the need to save the PTR and AT strings
from the garbage collector).

 Now there is just the issue of destroying strings manually. The following code
demonstrates that this issue is in fact caused by the garbage-collector trying to
destroy the  local strings in the method. By using a class variable that doesn't go
out of scope, everything works exactly as expected.

 Now, are these levels of indirection somehow available to the programmer? Maybe
a good idea would be to implement a way to manually add an address to the
garbage-collector. If i could do that, it would be awesome... either that, or have access
to the bstring for each string and destroy it manually.

 For now my code works stable, but i still need to handle the issue of the orphan strings.

P.S. Dont get me wrong, i know what you mean. The AT feature is to overlap an array
where we already know there are strings initialized. I just pointed out that it seems to work
when there aren't... but surely causes a leak of resources. :)
« Last Edit: August 17, 2019, 09:06:44 PM by Brian Alvarez »

Charles Pegge

  • Admin Support Member
  • *****
  • Posts: 4417
    • Oxygen Basic
Re: Volatility of variables...
« Reply #12 on: August 17, 2019, 09:44:02 PM »
Your program works because the object is dim'ed in global space and its string member dt is therefore also in global space. hm will contain a pointer to an entry on the global GC list. The string will only be freed at the end of the program.

However it is possible to use del on a string. This immediately frees the underlying bstring and nullifies the GC entry. But if this is done many times over, you will end up with a large GC list of null entries, which will be a form of memory leak.

The best way is to use bstring instead of string members inside the object, for stable storage, and free them within destructor(). (del dt)

Brian Alvarez

  • Hero Member
  • *****
  • Posts: 653
    • PluriBASIC
Re: Volatility of variables...
« Reply #13 on: August 17, 2019, 10:46:04 PM »
Okay I like the idea of using bstring, and i already tried it and it works. But then there is just
the issue of passing an array element BYREF to a function that expects the address of a string...
while retaining changes on the original bstring if the function it is passed to alters it....

 How would I do it?
« Last Edit: August 17, 2019, 10:55:29 PM by Brian Alvarez »

Brian Alvarez

  • Hero Member
  • *****
  • Posts: 653
    • PluriBASIC
Re: Volatility of variables...
« Reply #14 on: August 17, 2019, 10:53:20 PM »
 Either that... or purge null entries from the GC on demand maybe?....