It is currently Mon May 25, 2020 6:43 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 25 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Freeing Strings
PostPosted: Thu Aug 10, 2006 12:11 am 
Offline
Addict
Addict
User avatar

Joined: Thu Jul 01, 2004 2:51 am
Posts: 898
Location: Tacoma, WA
What's the generally accepted method for completely destroying the memory used by strings in a structure or elsewhere?

For example - this code ...

Code:
Structure s_Test
   a.s
   b.l
EndStructure
*HoldTest.s_Test = AllocateMemory(SizeOf(s_Test))
*HoldTest\a = "Hello World"
*HoldTest\b = 1978
q.l = @*HoldTest\a
FreeMemory(*HoldTest)
Debug PeekS(q)


... how should I completely erase the memory used by 'q' ? And I mean completely erase, not just ...

Code:
*HoldTest\a = ""


... unless that's the way to do it. Help?


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Aug 10, 2006 9:36 am 
Online
Addict
Addict
User avatar

Joined: Wed Jun 11, 2003 9:33 pm
Posts: 4623
Location: Spa, relaxing and thinking, and learning...
In the case (source) you have wrote, there is no doubt you really have freed the string buffer, because there is supposed the string is existent (allocated) by the program only in the case its pointer exists. If the string pointer is freed, the pointed string should automatically be vanished (i.e. its resources be freed) by the program (or by OS).
Keep in mind that even the contents of a mem buffer are not refilled with other data, it doesn't mean it has not been freed; i.e. FreeMemory() doesn´t fill freed heap with any data.

Besides i have seen now this:
Code:
df$="1234567890"
Debug MemorySize(@df$)
Debug Len(df$)

As you can see, the buffer always reports 5 bytes bigger than the lenght of the string. Which means that there is allocated the size of the string (i.e. len()+1) plus a longword which is a pointer, i think.
So not sure, but it seems that you can free any string doing like this:
Code:
FreeMemory(@df$)

This is the proof:
Code:
df$="1234567890"
Debug df$
Debug MemorySize(@df$)
Debug Len(df$)

;FreeMemory(@df$); <- uncomment to see the effect

Debug df$
Debug MemorySize(@df$)
Debug Len(df$)

_________________
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend


Last edited by Psychophanta on Thu Aug 10, 2006 9:55 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Aug 10, 2006 9:54 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sat Jun 28, 2003 12:01 am
Posts: 511
Have a look at this topic: http://www.purebasic.fr/english/viewtopic.php?p=133623

_________________
Windows 10 / Windows 7
PB Last Final / Last Beta Testing


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Aug 10, 2006 11:08 am 
Online
Addict
Addict
User avatar

Joined: Wed Jun 11, 2003 9:33 pm
Posts: 4623
Location: Spa, relaxing and thinking, and learning...
helpy wrote:

Opps, then, if the memory allocated by strings (or whatever) inside a structure is no deallocated when freeing the variable of the mentioned structure, there is a big big big fault. :!:

_________________
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Aug 10, 2006 11:13 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sat Jun 28, 2003 12:01 am
Posts: 511
Psychophanta wrote:
helpy wrote:

Opps, then, if the memory allocated by strings (or whatever) inside a structure is no deallocated when freeing the variable of the mentioned structure, there is a big big big fault. :!:


This happens only, if you dynamically create structures (AllocateMemory and pointer to structures). It does not happen with regular structured variables!

_________________
Windows 10 / Windows 7
PB Last Final / Last Beta Testing


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Aug 10, 2006 11:15 am 
Online
Addict
Addict
User avatar

Joined: Wed Jun 11, 2003 9:33 pm
Posts: 4623
Location: Spa, relaxing and thinking, and learning...
helpy wrote:
This happens only, if you dynamically create structures (AllocateMemory and pointer to structures). It does not happen with regular structured variables!

Aha! then there are some more of logic :)

_________________
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend


Top
 Profile  
Reply with quote  
 Post subject: Re: Freeing Strings
PostPosted: Thu Aug 10, 2006 12:23 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jul 04, 2004 12:15 pm
Posts: 284
Location: Germany
Xombie wrote:
What's the generally accepted method for completely destroying the memory used by strings in a structure or elsewhere?

...exactly what i wanted to ask today...

My solution:
Code:
Structure MyTest
  *MyPointer
  MyLong.l
  MyQuad.q
  MyString.s
EndStructure

*MyMem.MyTest = AllocateMemory(SizeOf(MyTest))
If *MyMem
  *MyMem\MyPointer = *MyMem
  *MyMem\MyLong    = $7FFFFFFF
  *MyMem\MyQuad    = $7FFFFFFFFFFFFFFF
  *MyMem\MyString  = "*MyMem\MyString Test"

  ptrDebug.l = @*MyMem\MyString
  Debug "-----------------"
  Debug *MyMem\MyPointer
  Debug *MyMem\MyLong   
  Debug *MyMem\MyQuad   
  Debug @*MyMem\MyString
  Debug "1: "+PeekS(ptrDebug)
 

  ; clear and free all allocated memory
  RtlZeroMemory_(@*MyMem\MyString,Len(*MyMem\MyString))
  FreeMemory(@*MyMem\MyString)
  RtlZeroMemory_(*MyMem,SizeOf(MyTest))
  FreeMemory(*MyMem)
  ; finished...

  Debug "-----------------"
  Debug *MyMem\MyPointer
  Debug *MyMem\MyLong   
  Debug *MyMem\MyQuad   
  Debug @*MyMem\MyString
  Debug "2: "+PeekS(ptrDebug)
  Debug "-----------------"
 
EndIf


I hope this is the correct way...

;-) sverson

[EDIT] see also SecureZeroMemory. (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/securezeromemory.asp)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Aug 10, 2006 4:01 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sat Jun 28, 2003 12:01 am
Posts: 511
I tried your code in a loop WITHOUT debugger! 5 loops are ok, but in the 6th the program crashes.

Code:
Structure MyTest
  *MyPointer
  MyLong.l
  MyQuad.q
  MyString.s
EndStructure

For i = 1 To 6
   *MyMem.MyTest = AllocateMemory(SizeOf(MyTest))
   If *MyMem
     *MyMem\MyPointer = *MyMem
     *MyMem\MyLong    = $7FFFFFFF
     *MyMem\MyQuad    = $7FFFFFFFFFFFFFFF
     *MyMem\MyString  = "*MyMem\MyString Test"
   
     ptrDebug.l = @*MyMem\MyString
     Debug "-----------------"
     Debug *MyMem\MyPointer
     Debug *MyMem\MyLong   
     Debug *MyMem\MyQuad   
     Debug @*MyMem\MyString
     Debug "1: "+PeekS(ptrDebug)
   
   
     ; clear and free all allocated memory
     RtlZeroMemory_(@*MyMem\MyString,Len(*MyMem\MyString))
     FreeMemory(@*MyMem\MyString)
     RtlZeroMemory_(*MyMem,SizeOf(MyTest))
     FreeMemory(*MyMem)
     ; finished...
   
     Debug "-----------------"
     Debug *MyMem\MyPointer
     Debug *MyMem\MyLong   
     Debug *MyMem\MyQuad   
     Debug @*MyMem\MyString
     Debug "2: "+PeekS(ptrDebug)
     Debug "-----------------"
   
   EndIf
Next i

_________________
Windows 10 / Windows 7
PB Last Final / Last Beta Testing


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Aug 10, 2006 4:54 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jul 04, 2004 12:15 pm
Posts: 284
Location: Germany
@helpy: same here!* :? (please take the above code as a question)

5..7 loops -> crash!

That's why i still look for a proper way to free strings inside structures.

FreeMemory(@*MyMem\MyString) does not work properly.

Your "workaround with a Macro" seems to be the only way ATM. :cry:
http://www.purebasic.fr/english/viewtopic.php?p=134805

@Fred:

Code:
While famous_TODO_list[FreeStructureStrings]<top
  PrintN("please...")
Wend
PrintN("Thanks ;-)")


;-) sverson


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Aug 10, 2006 6:07 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Jul 01, 2004 2:51 am
Posts: 898
Location: Tacoma, WA
That's ... slightly worrisome. It means that nearly all of my code leaks memory like a sieve. I used the allocation of structures to create a kind of array/linked list hybrid and use it in a lot of my stuff. I'll see about using helpy's macro examble while waiting for something official. Thanks, helpy.

So another question would be - why does ...

Code:
Structure s_test
   a.s
   b.l
EndStructure
*HoldTest.s_test = AllocateMemory(SizeOf(s_test))
*HoldTest\a = "Hello World"
*HoldTest\b = 1978
q.l = @*HoldTest\a
FreeMemory(*HoldTest)
Debug PeekS(q)
Debug *HoldTest\b


... return the 1978 for the second debug? If the memory is freed, the value should exist anywhere in memory, right?


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Aug 10, 2006 10:47 pm 
Offline
PureBasic Team
PureBasic Team
User avatar

Joined: Fri Apr 25, 2003 5:21 pm
Posts: 5805
Location: Germany
> ... return the 1978 for the second debug? If the memory is freed, the value should exist anywhere in memory, right?

By freeing the memory, you just tell the OS that you do not need it anymore. What the OS
then does with it cannot predicted.
The the memory (and its content) can remain for quite a while, or be invalidated
immediately. You may even receive the exact same pointer in a future AllocateMemory() call.

So if you have sensitive Information (like a password), overwriting it with 0 might be a good
thing before freeing the memory.

As for freeing the structured memory: Fred promised a function, but we are still working on
Linux, and with the Mac inbetween the next Update for Windows will be a while.

Using FreeMemory() on the PB strings is something you should do. Yes, i know it seems to work. (at least on some Windows versions)
The truth is though, that PB uses a different Memory heap for AllocateMemory and for the string management.
So theoretically, freeing the one thing with the function for the other (according to the API docs) should not work.
The Memory management of Windows is known to be very forgiving in this respect, so usually it works, yes.
I do not know if this is the case for all Windows versions though. Also the string handling on Linux/Mac is different, so it probably won't work there either.

Here is a very simple trick, that does the job quite nicely. It works on all OS, in PB 3.94 as well as 4.00 and probably will with future Versions as well.
The perfect function so to say ;). Its all about tricking PB into freein the String:
Code:
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.


Use it like this:
Code:
Structure MyStrings
  a.s
  b.s
  c.s
EndStructure

Procedure test()
  Protected *x.MyStrings = AllocateMemory(SizeOf(MyStrings))
 
  *x\a = Space(4000)
  *x\b = Space(4000)
  *x\c = Space(4000)
 
  FreePBString(@*x\a)
  FreePBString(@*x\b)
  FreePBString(@*x\c)
 
  FreeMemory(*x)
EndProcedure

CallDebugger

For i = 0 To 10000
  test()
Next i

CallDebugger

_________________
quidquid Latine dictum sit altum videtur


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Aug 10, 2006 11:30 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sat Jun 28, 2003 12:01 am
Posts: 511
That is really nice! Thank you, freak!

_________________
Windows 10 / Windows 7
PB Last Final / Last Beta Testing


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Aug 11, 2006 12:13 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jul 04, 2004 12:15 pm
Posts: 284
Location: Germany
freak wrote:
The perfect function so to say ;)

Great - thanks :)

After adding ZeroMemory it definitely is the perfect function!

Code:
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.
Code:
Structure MyStrings
  a.s
  b.s
  c.s
EndStructure

Procedure.l AvailPhysMem()
  Protected MemStat.MEMORYSTATUS
  GlobalMemoryStatus_(@MemStat)
  ProcedureReturn (MemStat\dwAvailPhys>>10)
EndProcedure

Procedure test()
  Protected *x.MyStrings = AllocateMemory(SizeOf(MyStrings))
 
  *x\a = Space(4000)
  *x\b = Space(4000)
  *x\c = Space(4000)
 
  ; DeletePBString(@*x\a,#True)
  ; DeletePBString(@*x\b,#True)
  ; DeletePBString(@*x\c,#True)
 
  FreeMemory(*x)
EndProcedure

Debug Str((4001*3*10000)>>10)+" Kb allocated!"

mem1.l = AvailPhysMem()
For i = 0 To 10000
  test()
Next i
mem2.l = AvailPhysMem()
Debug Str(mem1)+" Kb"
Debug Str(mem2)+" Kb"
Debug Str(mem1-mem2)+" Kb"
CallDebugger


Uncomment DeletePBString to to free and clear all strings.
There will remain just a little difference due to other programs allocate or free memory while the test is running.

;-) sverson


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Aug 11, 2006 9:55 am 
Online
Addict
Addict
User avatar

Joined: Wed Jun 11, 2003 9:33 pm
Posts: 4623
Location: Spa, relaxing and thinking, and learning...
freak wrote:
Code:
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.
:?:
I don't understand a thing :?
Can anybody explain that better? Or write the same code in ASM to undestand it?

_________________
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Aug 11, 2006 10:12 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sat Jun 28, 2003 12:01 am
Posts: 511
Psychophanta wrote:
freak wrote:
Code:
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.
:?:
I don't understand a thing :?
Can anybody explain that better? Or write the same code in ASM to undestand it?


"String.String" a local structure variable with ONE string element. All local structure variables are freed by PB when the procedure will be finished.

With "PokeL(@String, *Address) the passed string address is assigned to the structure variable. And know you have access to the string, which is identified by the passed string pointer, with the local structure variable String.String.

==> side effect: when the procedure is finished PB will free/release all local variables ... and also the local structure variables, which points to the passed string pointer.

Hope you understand a german native speaker ;-)

cu, helpy

_________________
Windows 10 / Windows 7
PB Last Final / Last Beta Testing


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 25 posts ]  Go to page 1, 2  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 13 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye