PureBasic v.5.70 -> Peeks() destroys Structures!

Just starting out? Need help? Post your questions and find answers here.
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

PureBasic v.5.70 -> Peeks() destroys Structures!

Post by Mijikai »

The example code shows how to get a 'string' from a dll.
Peeks() destroys the structure that is used to return a string (pointer).

Code (dll):

Code: Select all

EnableExplicit

Structure STRING_STRUCT
  *Buffer
  *Pointer
  String.s
EndStructure

Global Dummy.s = "2. Hello World!"

Macro mAllocString(p)
  p = AllocateStructure(STRING_STRUCT)
  If p
    p\String = #Null$
    p\Buffer = @p\String
    p\Pointer = @p\Buffer
  EndIf
EndMacro

ProcedureDLL.i Test1()
  Protected *Return.STRING_STRUCT
  mAllocString(*Return)
  If *Return
    *Return\String = "1. Hello World!"
    ProcedureReturn *Return\Pointer
  EndIf 
EndProcedure

ProcedureDLL.i Test2()
  Protected *Return.STRING_STRUCT
  mAllocString(*Return)
  If *Return
    *Return\String = PeekS(@Dummy);<- this will destroy the structure!
    ProcedureReturn *Return\Pointer
  EndIf
EndProcedure
Code (exe):

Code: Select all

EnableExplicit

Import "test.lib"
  Test1.i()
  Test2.i()
  FreeString.i(*String)
EndImport

Global *Test1.String
Global *Test2.String

*Test1 = Test1()
*Test2 = Test2()

Debug *Test1\s;<- works!
Debug *Test2\s;<- fails!

End
fryquez
Enthusiast
Enthusiast
Posts: 369
Joined: Mon Dec 21, 2015 8:12 pm

Re: PureBasic v.5.70 -> Peeks() destroys Structures!

Post by fryquez »

*Return\String = PeekS(@Dummy) - changes the address.

You need to update your structure elements.

\Buffer
\Pointer

are still pointing to the "old" string location.
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: PureBasic v.5.70 -> Peeks() destroys Structures!

Post by Mijikai »

It should only reallocate a already initialized string and not destroy it.
Peeks() returns a string (see help) and should behave like other functions (ex. Left(), StringField()) but it doesnt.
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: PureBasic v.5.70 -> Peeks() destroys Structures!

Post by Josh »

Code: Select all

Debug *Test1\s;<- works!
Debug *Test2\s;<- fails!
And whats the difference? Both show nothing. At least a working example would be good.

Next I would write the whole thing without DLL and without macro, there are possibly own errors much easier to recognize.
Last edited by Josh on Thu Jan 10, 2019 2:11 pm, edited 1 time in total.
sorry for my bad english
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: PureBasic v.5.70 -> Peeks() destroys Structures!

Post by Mijikai »

Josh wrote:

Code: Select all

Debug *Test1\s;<- works!
Debug *Test2\s;<- fails!
And whats the difference? Both show nothing.
Nice, then we have a huge bug.
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: PureBasic v.5.70 -> Peeks() destroys Structures!

Post by Mijikai »

Josh wrote: Next I would write the whole thing without DLL and without macro, there are possibly own errors much easier to recognize.
I noticed a possible bug/issue and posted it here to improve PB just so u know...
Nice comment really...
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: PureBasic v.5.70 -> Peeks() destroys Structures!

Post by Josh »

Mijikai wrote:Nice, then we have a huge bug.
I wouldn't say that. Your code is just crappy and meaningless and unnecessarily complicated that you don't understand it yourself.

This is again a typical example as we had it a few times in the last days. Don't understand the own code, but immediately post under bugs.
sorry for my bad english
User avatar
kenmo
Addict
Addict
Posts: 1967
Joined: Tue Dec 23, 2003 3:54 am

Re: PureBasic v.5.70 -> Peeks() destroys Structures!

Post by kenmo »

I don't think there's a bug.
fryquez is right, you're changing the string without updating the pointer to the old string.
PureBasic doesn't guarantee string pointers don't change. (What if PeekS was peeking a much larger string? Of course the pointer will have to change.)

Some other comments too:

Code: Select all

Structure STRING_STRUCT
  *Buffer
  ;*Pointer ; not needed, just return @*Return\Buffer
  String.s
EndStructure

Global Dummy.s = "2. Hello World!"

Macro mAllocString(p)
  p = AllocateStructure(STRING_STRUCT)
  If p
    Debug @p\String
    p\String = #Null$ ; this line doesn't change anything since p\String has never been set
    Debug @p\String
    Debug ""
    
    Debug p\Buffer
    p\Buffer = @p\String ; this line doesn't change anything since @p\String remains 0
    Debug p\Buffer
    Debug ""
  EndIf
EndMacro

ProcedureDLL.i Test1()
  Protected *Return.STRING_STRUCT
  mAllocString(*Return)
  If *Return
    *Return\String = "1. Hello World!"
    *Return\Buffer = @*Return\String ; update \Buffer to point to updated string
    ProcedureReturn @*Return\Buffer
  EndIf
EndProcedure

ProcedureDLL.i Test2()
  Protected *Return.STRING_STRUCT
  mAllocString(*Return)
  If *Return
    *Return\String = PeekS(@Dummy)
    *Return\Buffer = @*Return\String ; update \Buffer to point to updated string
    ProcedureReturn @*Return\Buffer
  EndIf
EndProcedure

Global *Test1.String
Global *Test2.String

*Test1 = Test1()
*Test2 = Test2()

Debug *Test1\s ; <- works
Debug *Test2\s ; <- works

; don't forget to free allocated structures...
; which might be impossible because you don't return the structure's address (*Return)

End
User avatar
mk-soft
Always Here
Always Here
Posts: 5406
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: PureBasic v.5.70 -> Peeks() destroys Structures!

Post by mk-soft »

I things is a better way to do it over memory

For all OS (Update 2 - UTF8)

Code: Select all

;-TOP

; -----------------------------------------------------------------------------

Procedure AllocateString(Text.s, Format = #PB_Unicode)
  Protected *mem, len
  
  len = StringByteLength(text, Format) + SizeOf(character)
  *mem = malloc_(len)
  If *mem
    PokeS(*mem, text, -1, Format)
  EndIf
  ProcedureReturn *mem
EndProcedure

; -----------------------------------------------------------------------------

Procedure.s FreeString(*Text)
  Protected result.s
  If *Text
    result = PeekS(*Text)
    free_(*Text)
  EndIf
  ProcedureReturn result
EndProcedure

; -----------------------------------------------------------------------------
  
ProcedureDLL _Get()
  Protected *result, text.s
  
  text = "Hello World!"
  *result = AllocateString(text)
  ProcedureReturn *result
  
EndProcedure

; -----------------------------------------------------------------------------

ProcedureDLL _Get_UTF8()
  Protected *result, text.s
  
  text = "Hello World!"
  *result = AllocateString(text, #PB_UTF8)
  ProcedureReturn *result
  
EndProcedure

; -----------------------------------------------------------------------------

CompilerIf #PB_Compiler_IsMainFile
  
  Prototype protoGet()
  
  Define lib.s, *mem
  
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
      lib = "mylib.dll"
    CompilerCase #PB_OS_Linux
      lib = "mylib.so"
    CompilerCase #PB_OS_MacOS
      lib = "mylib.dylib"
  CompilerEndSelect
  
  If OpenLibrary(0, lib)
    
    Get.protoGet = GetFunction(0, "_Get")
    Get_UTF8.protoGet = GetFunction(0, "_Get_UTF8")
    
    *mem = get()
    Debug "Adr: " + *mem + " - " + FreeString(*mem)
    *mem = get()
    Debug "Adr: " + *mem + " - " + FreeString(*mem)
    *mem = get()
    Debug "Adr: " + *mem + " - " + FreeString(*mem)
    
    *mem = Get_UTF8()
    Debug "UTF8 String / Adr: " + *mem + " - " + PeekS(*mem, -1, #PB_UTF8)
    free_(*mem)
  Else
    Debug "Error open Library!"
  EndIf
  
CompilerEndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Post Reply