Oxygen Basic
Programming => Bugs & Feature Requests => Topic started by: Brian Alvarez on August 16, 2019, 08:59:13 PM
-
Charles, i noticed strings are destroyed even if they were created with the AT switch:
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:
function strng(int hBuffer) as string
string ptr dt : @dt = hBuffer
return dt
end function
-
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):
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):
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...
-
Maybe i am too tired. I dont trust my eyes anymore. Ill get back to it tomorrow. Probably it is my fault somehow.
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)
-
One last post before bed time... Something anormal is messing with my code:
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:
*execution does not end here*
*But I should not be returned*
this is returned: >>*But I should not be returned*<<
-
Definately something needs fixing. Check this out:
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:
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: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<
-
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.
-
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??
-
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.
-
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
-
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.
-
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.
-
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:
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. :)
-
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)
-
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?
-
Either that... or purge null entries from the GC on demand maybe?....