Page 1 of 2

How to Free Memory without causing a memory leak

Posted: Mon Nov 18, 2019 7:03 pm
by StarBootics
Hello everyone,

I have question here, with the given code snippet how to free memory without causing a memory leak

Code: Select all

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Project name : Question
; File Name : How to Free Memory.pb
; File version: 1.0.0
; Programming : OK
; Programmed by : StarBootics
; Date : 18-11-2019
; Last Update : 18-11-2019
; PureBasic code : V5.71 LTS
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Memory = AllocateMemory(3*SizeOf(String))
*Ptr.String = Memory

*Ptr\s = "PureBasic"
*Ptr + SizeOf(String)

*Ptr\s = "Version 5.71 LTS x64"
*Ptr + SizeOf(String)

*Ptr\s = "November 18th, 2019"

FreeMemory(Memory)

Debug *Ptr\s

; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
Best regards
StarBootics

Re: How to Free Memory without causing a memory leak

Posted: Mon Nov 18, 2019 7:32 pm
by mk-soft

Code: Select all

; Bugfix PB v5.7x
CompilerIf #PB_Compiler_Version < 570
  Macro Nothing
    #Null$
  EndMacro
CompilerElse
  Macro Nothing
    "!_PB_NullConstant_!"
  EndMacro
CompilerEndIf

Memory = AllocateMemory(3*SizeOf(String))
*Ptr.String = Memory

*Ptr\s = "PureBasic"
*Ptr + SizeOf(String)

*Ptr\s = "Version 5.71 LTS x64"
*Ptr + SizeOf(String)

*Ptr\s = "November 18th, 2019"

*Ptr = Memory

*Ptr\s = Nothing
*Ptr + SizeOf(String)
*Ptr\s = Nothing
*Ptr + SizeOf(String)
*Ptr\s = Nothing

FreeMemory(Memory)

Debug *Ptr\s
Better over structure

Code: Select all

Structure udtString
  s1.s
  s2.s
  s3.s
EndStructure

*mem.udtString = AllocateStructure(udtString)

*mem\s1 = "PureBasic"
*mem\s2 = "Version 5.71 LTS x64"
*mem\s3 = "November 18th, 2019"

FreeStructure(*mem)

Debug *mem\s3 ; <- No memory leak. Old Data
I like this...

Code: Select all

Procedure FreeMemoryPtr(*Memory.integer)
  If *Memory
    FreeMemory(*Memory\i)
    *Memory\i = 0
  EndIf
EndProcedure

Procedure FreeStructurePtr(*Memory.integer)
  If *Memory
    FreeStructure(*Memory\i)
    *Memory\i = 0
  EndIf
EndProcedure

Structure udtString
  s1.s
  s2.s
  s3.s
EndStructure

*mem.udtString = AllocateStructure(udtString)

*mem\s1 = "PureBasic"
*mem\s2 = "Version 5.71 LTS x64"
*mem\s3 = "November 18th, 2019"

Debug *mem\s1 + #LF$ + *mem\s2 + #LF$ + *mem\s3

FreeStructurePtr(@*mem)

If *mem
  Debug *mem\s3
Else
  Debug "No Memory"
EndIf

Re: How to Free Memory without causing a memory leak

Posted: Mon Nov 18, 2019 7:43 pm
by StarBootics
Thanks for the quick response.

But I can't use a structure since I don't know in advance how many string I will have.

Best regards
StarBootics

Re: How to Free Memory without causing a memory leak

Posted: Mon Nov 18, 2019 7:44 pm
by IdeasVacuum
Hi StarBootics

- can't allocate memory as SizeOf(String), it's ambiguous?

Code: Select all

sMyString.s = "PureBasic" + #CRLF$ + "Version 5.71 LTS x64" + #CRLF$ + "November 18th, 2019"
     *MyMem = AllocateMemory(StringByteLength(sMyString, #PB_UTF8) + 1)
PokeS(*MyMem, sMyString, -1, #PB_UTF8)

Debug PeekS(*MyMem, -1, #PB_UTF8)

FreeMemory(*MyMem)
Edited: Allocate Memory: Add a byte for string end Null (0). Thanks mk-soft

Re: How to Free Memory without causing a memory leak

Posted: Mon Nov 18, 2019 7:49 pm
by mk-soft
Hi IdeasVacuum,

You forget Nullbyte... :mrgreen:

Code: Select all

*MyMem = AllocateMemory(StringByteLength(sMyString, #PB_UTF8) + 1) ; + SizeOf(Character) for ASCII and Unicode

Re: How to Free Memory without causing a memory leak

Posted: Mon Nov 18, 2019 7:57 pm
by mk-soft
Example 1

Code: Select all

;-TOP 

; For PB Function

Procedure MyString(Array Result.s(1))
  Protected cnt, i
  
  cnt = Random(10, 1)
  Dim Result(cnt)
  For i = 0 To cnt
    Result(i) = "Text " + Str(i)
  Next
  ProcedureReturn cnt
EndProcedure

Dim text.s(0)

Define c = MyString(text())

For i = 0 To c
  Debug text(i)
Next

Re: How to Free Memory without causing a memory leak

Posted: Mon Nov 18, 2019 7:58 pm
by Josh
StarBootics wrote:But I can't use a structure since I don't know in advance how many string I will have.
The use of an unstructured memory block is the worst solution to store pointers. If you want to store an unknown number of pointers, use a linked list consisting of pointers.

Code: Select all

NewList *MyPointers.String()

Re: How to Free Memory without causing a memory leak

Posted: Mon Nov 18, 2019 8:38 pm
by mk-soft
Example 2

Bugfix - forget free buffer

Code: Select all

;-TOP 

; For DLL like API

Procedure Unicode(Text.s)
  Protected *mem = AllocateMemory(StringByteLength(Text) + SizeOf(Unicode))
  If *mem
    PokeS(*mem, Text, -1, #PB_Unicode)
  EndIf
  ProcedureReturn *mem
EndProcedure

; ----

Global NewMap CheckStringBuffer.i()

ProcedureDLL MyStringResult(*Buffer.integer)
  Protected *mem.integer, cnt
  
  If *Buffer = 0
    ProcedureReturn -1 ; Invalid Pointer
  EndIf
  
  cnt = Random(10, 1)
  
  *mem = AllocateMemory((cnt + 2) * SizeOf(integer)) 
  If *mem
    AddMapElement(CheckStringBuffer(), Str(*mem))
    CheckStringBuffer() = cnt
    *Buffer\i = *mem
    For i = 0 To cnt
      *mem\i = Unicode("Text " + Str(i))
      *mem + SizeOf(integer)
    Next
    ProcedureReturn cnt + 1
  Else
    ProcedureReturn -2 ; Out Of Memory
  EndIf
EndProcedure

ProcedureDLL MyFreeString(*Buffer)
  Protected *mem.integer = *Buffer
  If *Buffer
    If FindMapElement(CheckStringBuffer(), Str(*Buffer))
      *mem = *Buffer
      While *mem\i
        FreeMemory(*mem\i)
        *mem\i = 0
        *mem + SizeOf(integer)
      Wend
      FreeMemory(*Buffer)
      DeleteMapElement(CheckStringBuffer())
    EndIf
  EndIf
EndProcedure
  
; ----

Define *Buffer
Define cnt

cnt = MyStringResult(@*Buffer)
Debug "Count: " + cnt
If cnt > 0
  *string = *Buffer
  For i = 1 To cnt
    Debug PeekS(PeekI(*string))
    *string + SizeOf(integer)
  Next
EndIf

MyFreeString(*Buffer)

Re: How to Free Memory without causing a memory leak

Posted: Mon Nov 18, 2019 9:33 pm
by IdeasVacuum
Hi mk-soft ... The null byte is automatically added by PB - you have to use a flag to omit it if required.

Edit: Ah no, you mean the allocation - yes, should be 1 byte added for Null.

Re: How to Free Memory without causing a memory leak

Posted: Mon Nov 18, 2019 9:42 pm
by mk-soft
Sorry, but your memory is to short...

StringByteLen give the length of string without null byte.

Code: Select all

len = StringByteLength("0123456789")
Debug Len
PokeS write with null byte over your memory size...

Ok, you have see. Sorry

Re: How to Free Memory without causing a memory leak

Posted: Wed Nov 20, 2019 4:26 pm
by IdeasVacuum
Hi StarBootics
I don't know in advance how many string I will have
Why not simply use a List (linked List)? It's a powerful, fast and easy way to manage an unknown number of strings.

Re: How to Free Memory without causing a memory leak

Posted: Wed Nov 20, 2019 4:40 pm
by Josh
IdeasVacuum wrote:Why not simply use a List (linked List)? It's a powerful, fast and easy way to manage an unknown number of strings.
This or a list of pointers, as I have described above. Unfortunately it is not possible to see what StarBootics actually intends.

Re: How to Free Memory without causing a memory leak

Posted: Wed Nov 20, 2019 5:44 pm
by StarBootics
Josh wrote:
IdeasVacuum wrote:Why not simply use a List (linked List)? It's a powerful, fast and easy way to manage an unknown number of strings.
This or a list of pointers, as I have described above. Unfortunately it is not possible to see what StarBootics actually intends.
It's very simple, I want to create a data structure that I manage my self like I did with my ByteVector but for string instead of byte.

Best regards
StarBootics

Re: How to Free Memory without causing a memory leak

Posted: Wed Nov 20, 2019 10:06 pm
by Josh
StarBootics wrote:It's very simple, I want to create a data structure that I manage my self like I did with my ByteVector but for string instead of byte.
With the code you linked, I tried to change it to lists. So your question from here shouldn't be an issue anymore.

Re: How to Free Memory without causing a memory leak

Posted: Wed Nov 20, 2019 10:53 pm
by StarBootics
Josh wrote:
StarBootics wrote:It's very simple, I want to create a data structure that I manage my self like I did with my ByteVector but for string instead of byte.
With the code you linked, I tried to change it to lists. So your question from here shouldn't be an issue anymore.
If I wanted to use a linked list to store the data I would have done it that way, it's clear. And it's exactly what I don't want to do.

Best regards
StarBootics