using allocate/reallocate/deallocate for zstring

New to FreeBASIC? Post your questions here.
Post Reply
StillLearning
Posts: 52
Joined: Aug 27, 2019 22:22

using allocate/reallocate/deallocate for zstring

Post by StillLearning »

Hello,
I have read all of the documentation on using allocate/reallocate/deallocate for zstrings. I created a small test program to
test my knowledge. From the results of my test program I saw no benefits in using the allocate/reallocate/deallocate for zstrings.
I was under the assumption than if a zstring was initially set to a fixed size by using allocate and then resized to a smaller size
by using reallocate that the max size of the zstring would change to that size, from my testing (unless I am wrong in my testing code)
If a zstring is set to 128 and then the memory is reallocated to a smaller size and then copy the zstring to a dynamic string then the size of dynamic
string is changed but the data for the string is still there except a null (0) will be at the index location inside that string. So is there a
way to resize a zstring that is smaller to that size when copied to a dynamic string?

Code: Select all

Dim SymbolTbl(0 to 6) as string
Dim Buffer as zstring ptr 
Buffer = cAllocate(128)
dim index as byte
dim strh as string
Dim Buffer2 as zstring*128


'buffer should be 128 bytes long
SymbolTbl(1) = *Buffer
Print "len(SymbolTbl(1)) = ";len(SymbolTbl(1))
print "sizeof (SymbolTbl(1)) = ";sizeof(SymbolTbl(1))

*Buffer = "myva"

Print "len(*Buffer) = ";len(*Buffer)
print "sizeof (*Buffer) = ";sizeof(*Buffer)

Buffer = reallocate(Buffer,9)

SymbolTbl(0) = *Buffer

Print "len(SymbolTbl(0)) = ";len(SymbolTbl(0))
print "sizeof (SymbolTbl(0)) = ";sizeof(SymbolTbl(0))

*Buffer = "myvar equ"
SymbolTbl(2) = *Buffer
strh = SymbolTbl(2)
Print "len(SymbolTbl(2)) = ";len(SymbolTbl(2))
print "sizeof (SymbolTbl(2)) = ";sizeof(SymbolTbl(2))
for Index = 0 to 16
print "SymbolTbl(2) char "; Index ; " ";strh[index]
next



'now do the same thing without allocate/deallocate

'buffer should be 128 bytes long
SymbolTbl(5) = Buffer2
Print "len(SymbolTbl(5)) = ";len(SymbolTbl(5))
print "sizeof (SymbolTbl(5)) = ";sizeof(SymbolTbl(5))

Buffer2 = "myva"

Print "len(Buffer2) = ";len(Buffer2)
print "sizeof (Buffer2) = ";sizeof(Buffer2)

SymbolTbl(4) = Buffer2

Print "len(SymbolTbl(4)) = ";len(SymbolTbl(4))
print "sizeof (SymbolTbl(4)) = ";sizeof(SymbolTbl(4))

Buffer2 = "myvar equ"
SymbolTbl(6) = Buffer2
strh = SymbolTbl(6)
Print "len(SymbolTbl(6)) = ";len(SymbolTbl(6))
print "sizeof (SymbolTbl(6)) = ";sizeof(SymbolTbl(6))
for Index = 0 to 16
print "SymbolTbl(6) char "; Index ; " ";strh[index]
next

Deallocate(buffer)
fxm
Moderator
Posts: 11423
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: using allocate/reallocate/deallocate for zstring

Post by fxm »

1)
The "Sizeof" keyword applied to a (var-len) string variable always returns the size of the string descriptor.

2)
When allocating memory for zstring, a byte in addition to the useful characters should be allocated to hold the terminal character (0).
So since "myvar equ" contains 9 characters, the memory must be reallocated to 10 bytes:
Buffer = reallocate(Buffer,10)

3)
When you reallocate memory to smaller memory, the freed bytes become available, but their values are not changed until they are used for another memory allocation.
Reallocating does not reset the freed bytes.

4)
For (var-len) strings (dynamic strings), allocated memory is handled under the hood, and memory allocation/reallocation is done in large steps to improve execution time.
The allocated memory size is usually greater than (or sometimes equal to) the useful string size, and this allocated memory size (available memory for string characters) is stored in the string descriptor (in addition to the address of the first character and the number of characters actually used).
StillLearning
Posts: 52
Joined: Aug 27, 2019 22:22

Re: using allocate/reallocate/deallocate for zstring

Post by StillLearning »

Thank you for the information fxm.

one question:

1. In my example a save the contents of the zstring to a dynamic string array. I want to use a pointer to access that same array.
I saw no examples on how to have a pointer created to access the contents of a dynamic string array. How do I do this?

Thank you for your help.

StillLearning
dodicat
Posts: 7652
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: using allocate/reallocate/deallocate for zstring

Post by dodicat »

I think you have to do it pedantically, and not drift off into dreamtime.

Code: Select all

Sub memcopy(dest As Any Ptr,src As Any Ptr,count As Long)
    Dim As Ubyte Ptr newdst=dest
    Dim As Ubyte Ptr newsrc=src
    For n As Long=0 To count
        newdst[n]=newsrc[n]
    Next n
End Sub

dim as zstring ptr z
z=strptr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ --- Hello.")
print "'";*z;"'"

redim as ubyte a(len(*z)-1)

memcopy(@a(0),z,ubound(a))
'access via raw data
print "'";
for n as long=0 to ubound(a)
      print chr(a(n));
next
print "'"
print

'========= OR =====
print "'";*cast(zstring ptr,@a(0));"'" 'access via pointer
redim a(25)
memcopy(@a(0),z,ubound(a))
print "'";*cast(zstring ptr,@a(0));"'" 'access via pointer
sleep 
fxm
Moderator
Posts: 11423
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: using allocate/reallocate/deallocate for zstring

Post by fxm »

StillLearning wrote: Oct 03, 2022 15:56 1. In my example a save the contents of the zstring to a dynamic string array. I want to use a pointer to access that same array.
I saw no examples on how to have a pointer created to access the contents of a dynamic string array. How do I do this?
1)
Use the 'StrPtr()' (String Pointer) keyword.
(the '@' operator only allows access to the descriptor of a var-len string)
Simplest code:

Code: Select all

Dim SymbolTbl(0 To 6) As String
SymbolTbl(3) = "Hello to the forum!"

Dim As Zstring Ptr pz = Strptr(SymbolTbl(3))
Print *pz

Sleep
Note:
- After each modification of the size of a var-len string, the string character data may be moved in memory.
- Therefore, the value of the pointer to the string character data must be re-evaluated after each change in the size of the string.

2)
Instead, by using a pointer to pointer (pointer to the address of the string character data in the string descriptor), there is no more readjustment to be done after each string size change (the address in the string descriptor is still valid, and the string descriptor is still at the same address):

Code: Select all

Dim SymbolTbl(0 To 6) As String
Dim As Zstring Ptr Ptr ppz = Cptr(Zstring Ptr Ptr, @SymbolTbl(3))

SymbolTbl(3) = "Hello to the forum!"
Print *ppz[0]

Sleep

By using a reference to the address contained in the string descriptor, a single user dereferencing is enough to access the character data of the string at any time (the second dereferencing is done under the hood):

Code: Select all

Dim SymbolTbl(0 To 6) As String
Dim Byref As Zstring Ptr rpz = Cptr(Zstring Ptr Ptr, @SymbolTbl(3))[0]

SymbolTbl(3) = "Hello to the forum!"
Print *rpz

Sleep

3)
The worst case is when the string array is also dynamic (of variable length when the upper limit of its dimension is modified).
In this case, the indirection must pass through the descriptor of the array before addressing the descriptor of the string (the string descriptors are the elements of the array which may be also moved in memory).

Using a pointer to the address of the string character data in the string descriptor:

Code: Select all

#include once "fbc-int/array.bi"

Redim SymbolTbl(0 To 6) As String
Dim As Zstring Ptr Ptr ppz = Cptr(Zstring Ptr Ptr, Cptr(String Ptr Ptr, FBC.ArrayDescriptorPtr(SymbolTbl()))[0] + 3)

SymbolTbl(3) = "Hello to the forum!"
Print *ppz[0]

Sleep

Using a reference to the address of the string character data in the string descriptor:

Code: Select all

#include once "fbc-int/array.bi"

Redim SymbolTbl(0 To 6) As String
Dim Byref As Zstring Ptr rpz = Cptr(Zstring Ptr Ptr, Cptr(String Ptr Ptr, FBC.ArrayDescriptorPtr(SymbolTbl()))[0] + 3)[0]

SymbolTbl(3) = "Hello to the forum!"
Print *rpz

Sleep

These last 2 codes also (obviously) work for a static array (of fixed length).
Post Reply