Program crash when pass Wstring array as parameter

General FreeBASIC programming questions.
Post Reply
geminis4941
Posts: 64
Joined: Jul 15, 2009 12:41

Program crash when pass Wstring array as parameter

Post by geminis4941 »

When I pass a big Wstring as parameter the code crash.It dont happens with strings.

Compiler : FreeBASIC-0-90

Code: Select all

 
'set up some values
Dim as Integer n=200000
Dim Shared  arr2(1 to n) as WString*50

Sub combsort( arr1() As WString*50,begin As integer,finish As Integer)
    Dim  size As Integer=(finish)
    Dim switch As Integer=0
    Dim j As Integer=0
    Dim As Single void=size
    Dim aux As WString*50
    Do
        void=void/1.3: If void<1 Then void=1
        switch=0
        For i As Integer =begin To size-void
            j=i+void
            If arr1(i)>arr1(j) Then
                aux= arr1(i)
                arr1(i)=arr1(j)
                arr1(j)=aux
                switch=1
            End If
        Next
    Loop Until  switch =0 And void=1
End Sub

'example

Randomize
for i as Integer=1 to n
    arr1(i)= "element " + Str(CInt(rnd*100))
Next 

combsort(arr2(),1,UBound(arr2))

sleep

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

Re: Program crash when pass Wstring array as parameter

Post by dodicat »

fixed length strings as a sub parameter give a compiler error.
something like:
Illegal specification, at parameter ...

fixed length wstrings cause a segmentation error OR a corrupt result.

You could use a combsort macro instead.

Code: Select all


 
'set up some values
Dim as Integer n=200000
Dim Shared  arr2(1 to n) as WString * 50

#macro combsort( arr1,begin,finish)
#print typeof(arr1)
scope
    Dim  size As Integer=(finish)
    Dim switch As Integer=0
    Dim j As Integer=0
    Dim As Single void=size
    Dim aux As typeof(arr1)' i.e.  WString * 50
    Do
        void=void/1.3: If void<1 Then void=1
        switch=0
        For i As Integer =begin To size-void
            j=i+void
            If arr1(i)>arr1(j) Then
                aux= arr1(i)
                arr1(i)=arr1(j)
                arr1(j)=aux
                switch=1
            End If
        Next
    Loop Until  switch =0 And void=1
    end scope
#endmacro

'example

Randomize
for i as Integer=1 to n
    arr2 (i)= "element " + Str(CInt(rnd*1000000))
Next 

combsort(arr2,1,UBound(arr2))

for i as Integer=1 to 50
    print i, arr2 (i)
Next 
sleep
 
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Program crash when pass Wstring array as parameter

Post by fxm »

Look at #650.
Don't work neither with fix-len Wstring, nor with fix-len Zstring and nor with fix-len String.
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Program crash when pass Wstring array as parameter

Post by fxm »

A workaround could be to always use the fix-len string, but packed into an UDT, as:

Code: Select all

Type WString50
  Dim As WString*50 w
End Type
[edit]
With:
Dim Shared arr(1 to n) as WString50
one wstring is accessible by the syntax:
arr(i).w
Last edited by fxm on Nov 04, 2016 8:14, edited 3 times in total.
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Program crash when pass Wstring array as parameter

Post by fxm »

Your code, but slightly modified only, by using an improved UDT defining an overloaded Cast and Let operator:
('arr(i).w' can be shortcut by the 'arr(i)' usage which then calls the Cast or Let operator, but at some expense of execution speed)

Code: Select all

Type WString50
  Dim As WString*50 w
  Declare Operator Cast () Byref As WString
  Declare Operator Let (Byref w0 As WString)
End Type
Operator WString50.Cast () Byref As WString
  Return This.w
End Operator
Operator WString50.Let (Byref w0 As WString)
  This.w = w0
End Operator

'set up some values
Dim as Integer n=200000
Dim Shared  arr2(1 to n) as WString50


Sub combsort( arr1() As WString50,byval begin As integer,byval finish As Integer)
    Dim  size As Integer=(finish)
    Dim switch As Integer=0
    Dim j As Integer=0
    Dim As Single void=size
    Dim aux As WString*50
    Do
        void=void/1.3: If void<1 Then void=1
        switch=0
        For i As Integer =begin To size-void
            j=i+void
            If arr1(i)>arr1(j) Then
                aux= arr1(i)
                arr1(i)=arr1(j)
                arr1(j)=aux
                switch=1
            End If
        Next
    Loop Until  switch =0 And void=1
End Sub

'example

Randomize
for i as Integer=1 to n
    arr2(i)= "element " + Str(CInt(rnd*100))
Next

combsort(arr2(),1,UBound(arr2))

sleep
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Program crash when pass Wstring array as parameter

Post by fxm »

Remark:
In FreeBASIC, the instruction 'Swap' exists, so that the following loop of the code:

Code: Select all

        For i As Integer =begin To size-void
            j=i+void
            If arr1(i)>arr1(j) Then
                aux= arr1(i)
                arr1(i)=arr1(j)
                arr1(j)=aux
                switch=1
            End If
        Next
can be shortened by:

Code: Select all

        For i As Integer =begin To size-void
            j=i+void
            If arr1(i)>arr1(j) Then
                Swap arr1(i), arr1(j)
                switch=1
            End If
        Next
Juergen Kuehlwein
Posts: 284
Joined: Mar 07, 2018 13:59
Location: Germany

Re: Program crash when pass Wstring array as parameter

Post by Juergen Kuehlwein »

I think i found, where the bug (cannot pass w/zstring arrays) comes from, and i have a fix. There will be a pull request for this in a few days.

JK
Juergen Kuehlwein
Posts: 284
Joined: Mar 07, 2018 13:59
Location: Germany

Re: Program crash when pass Wstring array as parameter

Post by Juergen Kuehlwein »

Pull request #158 solves the problem of z/wstring arrays passed as parameter not working properly. This is because the size of z/wstrings passed as parameter is lost. For z/wstring arrays the size of an element is stored in the array descriptor too. I added RtlCalcStrLen2, which accounts for this by using the size held in the descriptor for bydesc parameters.

For "regular" z/wstring parameters access and assignment works, but it is possible to cause overflow for such parameters

Code: Select all

dim z as zstring * 3 = "asdf"

sub showa(z as zstring)
  print hex(varptr(z)), z
  z = "qwertz"   
end sub


showa(z)
print hex(varptr(z)), z

sleep
end 
JK
Post Reply