String pointers

BlitzMax Forums/BlitzMax Programming/String pointers

Hum having a bit of trouble since upgrading to the latest version.

Basically what the problem is, is that in my config system im registering variables with it like this...

	' Adds a new string configuration variable
	Method BindStringCfgVar:TConfigVar(Path:String,Variable:String Var,Index:Int = 0)
	
		' Create new variable
		Local CVar:TConfigVar 	  = New TConfigVar
			  CVar.Path			  = Path
			  CVar.VarType 	   	  = TConfigVar._STRING
			  CVar.StringVariable = VarPtr(Variable)
			  CVar.Index	 	  = Index
						
		' Add it to the list
		ListAddLast(VariableList,CVar:TConfigVar)
	
		' Return the new config variable
		Return CVar:TConfigVar
	
	End Method


And i would write several lines like this to register a my variables.

BindStringCfgVar("Settings::Audio::API",_audio_api,0)


And then when the config system parses the file it would assign the values it finds to the correct variables like so...


		For Local CfgVar:TConfigVar = EachIn VariableList

			' Set value depending on variable type
			Select CfgVar.VarType
			
				' String value
				Case TConfigVar._STRING	
					CfgVar.StringVariable[0] = Scf.GetNodeAsString(CfgVar.Path,CfgVar.Index)						
			End Select
			
		Next	



Unfortunatly i cant do that now as pointers to objects are invalid so i was wandering if anyone knew of another way of doing this, as i really dont want to have a large select block to check what each variable each value should be assigned to.

Ha I knew I would succeed ;-)

Strict

Type Test
	Field name:String
	Field StringVar:Byte Ptr
	
	Method toString1()
		Print "Name: " + name
		Print "StringVar: " + String.fromCString(StringVar) 
	End Method
	
End Type


Local teststring:Byte Ptr	= "Test Ptr".toCString()
Local aka:test 			= New test
aka.name	 		= "test"
aka.StringVar			= teststring

Print aka.tostring1() 

MemCopy(teststring,"Papa".toCString(),Len("Papa")+1)
aka.tostring1()



Hope this helps ... and thank you for the Script Module

unfortunatly doing that leaks memory try this

Strict

Type Test
	Field name:String
	Field StringVar:Byte Ptr
	
	Method toString1()
		Print "Name: " + name
		Print "StringVar: " + String.fromCString(StringVar) 
	End Method
	
End Type


Local teststring:Byte Ptr	= "Test Ptr".toCString()
Local aka:test 			= New test
aka.name	 		= "test"
aka.StringVar			= teststring

Print aka.tostring1() 


For Local n:Int=0 To 10000000
	Local ts:Byte Ptr= "Papa".toCString()
	MemCopy(teststring,ts,Len("Papa")+1)
	MemFree ts
	aka.tostring1()
Next 
MemFree teststring



and thry doing the same with your example without the memfree's when your code runs the memory used (as reported by a process explorer continually increases)

using the code I have posted here the mem usage stays stable

You are right.
It was only meant as a general idea on how to get around it. Wrapping it into a function that sets the content would be simpler anyway. For example like

Function SetCString(target:byte ptr, in:string)
	Local ts:Byte Ptr= in.toCString()
	MemCopy(target,ts,Len(in)+1)
	MemFree ts
end function


Thanks guys that should be helpfull, ill try it out tommorrow


and thank you for the Script Module


Your welcome, always nice to share with the community.

I just realized something: The above method is a really dangerous one!
It can potentially overwrite other objects handled by the GC.

Here a fixed version.
Btw: You need to init the stringptr as well with that size when you create it. I created the init method for that.

Strict
Type CVar
	Field name:String
	Field namePtr:Byte Ptr
	
	Method init(length:Int)
		' Length is the max length of the strings you want to use
		' +1 is needed for the C Stringterminator char (chr(0))
		namePtr	 = MemAlloc(length+1)
	End Method
End Type


Function SetCString(target:Byte Ptr, in:String)
	' Lets say there is a constant max_len that defines the max string len
	Local ts:Byte Ptr
	If in.length > max_len
		in	 	= Left(in , max_len)
		ts		= in.toCString()
	Else
		Local tm:Byte Ptr		= MemAlloc(max_len + 1)
		ts		= in.toCString()
		MemCopy(tm , ts , in.length + 1) 
		MemFree ts
		ts		 = tm
	EndIf 
	MemCopy(target,ts,max_len+1)
	MemFree ts
End Function



Const max_len:Int	 = 20

Local test:cvar = New cvar
test.name	 = "Test"
test.init(max_len)
Print "Memory: " + GCMemAlloced()
For Local i = 0 To 100000000
	setCString(test.namePtr , "Test: " + i)
Next

Print "Memory: " + GCMemAlloced()
End


*sorry that I had to remove the code. had a little nifty memoryleak ;-)*