Page 2 of 2

Posted: Fri Aug 11, 2006 10:25 am
by Psychophanta
Thank you Helpy, you are a Helper :)
In fact this trick uses the PB internals.
It is curious (and understandable) that when used another local variable than string type it doesn't work, so i got crazy, but now it is clear.
However i see there is dangerous to play with the pointers of the strings, over all when them is passed to functions. :o

Posted: Fri Aug 11, 2006 11:03 am
by helpy
There is a conflict with the debugger!

Code: Select all

Structure MyStrings
	StructureUnion
  	a.s
  	pa.l
  EndStructureUnion
EndStructure

Procedure FreePBString(*Address)
  Protected String.String  ; the String Structure contains one String element, which is initialized to 0 on procedure start
  PokeL(@String, *Address) ; poke our strings address into the structure
EndProcedure               ; when returning, PB's string free routine for the local structure will actually free the passed string.

*x.MyStrings = AllocateMemory(SizeOf(MyStrings))

For x = 1 To 2
	*x\a = "A String ..."
	Debug Str(*x\pa) + " - " + *x\a
	
	FreePBString(@*x\a)
	Debug Str(*x\pa) + " - " + *x\a
Next x
 
FreeMemory(*x)
With debugger on it crashes when FreePBString is called the second time.

Without debugger it works without a crash.

cu, helpy

Posted: Fri Aug 11, 2006 11:46 am
by Psychophanta
If you free the .s field, you need to Allocate memory again for the variable.
Which means that the correct and safe way is to FreeMemory() after use the Timo's function, and then allocate again for the next loop.
Like that:

Code: Select all

Structure MyStrings
   StructureUnion
     a.s
     pa.l
  EndStructureUnion
EndStructure

Procedure FreePBString(*Address)
  Protected String.String  ; the String Structure contains one String element, which is initialized to 0 on procedure start
  PokeL(@String, *Address) ; poke our strings address into the structure
EndProcedure               ; when returning, PB's string free routine for the local structure will actually free the passed string.

For x = 1 To 2
  *x.MyStrings = AllocateMemory(SizeOf(MyStrings))

   *x\a = "A String ..."
   Debug Str(*x\pa) + " - " + *x\a
    
   FreePBString(@*x\a)
   Debug Str(*x\pa) + " - " + *x\a
  FreeMemory(*x.MyStrings)
Next x

Re: Freeing Strings

Posted: Sun Aug 13, 2006 1:25 pm
by mskuma
sverson wrote:see also SecureZeroMemory. (http://msdn.microsoft.com/library/defau ... memory.asp)
I was just having a look at this tonight.. unless I'm mistaken, it doesn't seem to work in PB4?

Code: Select all

SecureZeroMemory_(*buff, MemorySize(*buff)) ; fails with 'not function' error
but

Code: Select all

ZeroMemory_(*buff, MemorySize(*buff))   ; is ok

Posted: Mon Aug 14, 2006 12:10 am
by sverson
@mskuma:
  • http://msdn.microsoft.com/library/en-us ... frame=true
    ...The effect of RtlSecureZeroMemory is identical to that of RtlZeroMemory, except that it is guaranteed to zero the memory location, even if it is not subsequently written to. (The compiler can optimize away a call to RtlZeroMemory, if it determines that the caller does not access that memory range again.)...
Maybe PB does not optimize away a call to RtlZeroMemory so RtlZeroMemory does the job and RtlSecureZeroMemory is not needed?!?

;-) sverson

Posted: Mon Aug 14, 2006 12:26 am
by mskuma
Hi sverson. Thanks for your comment.
sverson wrote:Maybe PB does not optimize away a call to RtlZeroMemory so RtlZeroMemory does the job and RtlSecureZeroMemory is not needed?!?
Maybe.. who know? The above statement is similar to the one for SecureZeroMemory, i.e.
Use this function instead of ZeroMemory when you want to ensure that your data will be overwritten promptly, as the compiler can optimize a call to ZeroMemory by removing it entirely. A call to SecureZeroMemory will not be optimized.
My concern was I thought PB supported any WinAPI command by simply post-pending the underscore character to the function, but in this case (using SecureZeroMemory & also RtlZeroMemory) fails giving the error I mentioned. I'm not understanding something about PB obviously.

This issue about optimising away a statement is interesting though. I guess it only applies to MS tools :wink:

Posted: Sat Feb 17, 2007 3:27 pm
by srod
Have followed this thread with interest and now that I find myself using dynamically allocated structures containing strings, I am at last using Freak's tip.

I have one almost daft question, but I want to be absolutely sure that all memory is being freed correctly.

@Freak: in the following code which uses your 'perfect function' :) ,

Code: Select all

Structure MyStrings 
  a.s 
EndStructure 

Procedure test() 
  Protected *x.MyStrings = AllocateMemory(SizeOf(MyStrings)) 
  
  *x\a = "Testing!"
  *x\a = "Will the preceeding string 'Testing' be freed by this allocation?"
  
  FreePBString(@*x\a) 
  
  FreeMemory(*x) 
EndProcedure 

CallDebugger 

For i = 0 To 10000 
  test() 
Next i 

CallDebugger
will the command:

Code: Select all

*x\a = "Will the preceeding string 'Testing' be freed by this allocation?"
automatically free the memory allocated by the previous command

Code: Select all

*x\a = "Testing!"
?

Common sense dictates an answer of 'yes, don't be an idiot all of your life' :) , but as I say I just want to be 100% sure that I am left with no memory leaks.

Thanks.

Posted: Sat Feb 17, 2007 3:32 pm
by Trond
Yes it will be freed.

Posted: Sat Feb 17, 2007 3:48 pm
by srod
Thanks. Always worth asking if even a tiny amount of doubt festers! :)

Posted: Fri Jul 20, 2007 5:16 pm
by Nico

Code: Select all

Procedure DeletePBString(*Address,delete.b=#False)
  Protected String.String                  ; the String Structure contains one String element, which is initialized to 0 on procedure start
  PokeL(@String, *Address)                 ; poke our strings address into the structure
  If delete
    RtlZeroMemory_(*Address,Len(String\s)) ; fill the String with zero
  EndIf
EndProcedure                               ; when returning, PB's string free routine for the local structure will actually free the passed string.
-->RtlZeroMemory_(*Address,Len(String\s)+1)