ChangeCurrentElement()

Just starting out? Need help? Post your questions and find answers here.
Little John
Addict
Addict
Posts: 4519
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

ChangeCurrentElement()

Post by Little John »

In the third-last line of the following code, ChangeCurrentElement() changes to an element that does not exist anymore!
In the next line, Debug shows the content of that not-existing element!

Fred, when you are working on ChangeCurrentElement() anyway for fixing this bug, it probably won't be much additional work to implement this related wish. :-)

Code: Select all

; PB 5.71 beta 2 (x64) on Windows 10

EnableExplicit

Define *p
NewList lst.i()

AddElement(lst()) : lst() = 12
AddElement(lst()) : lst() = 15
*p = @ lst()
Debug @ lst()                      ; -> 7998400 in my test
Debug lst()                        ; -> 15 (as expected)

DeleteElement(lst())
Debug ListSize(lst())              ; -> 1  (as expected)
Debug @ lst()                      ; -> 7998368 in my test
Debug lst()                        ; -> 12 (as expected)

ChangeCurrentElement(lst(), *p)
Debug @ lst()                      ; -> 7998400 in my test (How is that possible???)
Debug lst()                        ; -> 15                 (How is that possible???)
freak
PureBasic Team
PureBasic Team
Posts: 5929
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: ChangeCurrentElement()

Post by freak »

The documentation states:
The element must be a pointer to another element which exists in this list.
You called the function with invalid input, hence the behavior is undefined.

No bug.
quidquid Latine dictum sit altum videtur
User avatar
chi
Addict
Addict
Posts: 1028
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

Re: ChangeCurrentElement()

Post by chi »

Code: Select all

; PB 5.71 beta 2 (x64) on Windows 10

EnableExplicit

Define *p
NewList lst.i()

AddElement(lst()) : lst() = 12
AddElement(lst()) : lst() = 15
*p = @ lst()
Debug @ lst()                      ; -> 7998400 in my test
Debug lst()                        ; -> 15 (as expected)

DeleteElement(lst())
Debug ListSize(lst())              ; -> 1  (as expected)
Debug @ lst()                      ; -> 7998368 in my test
Debug lst()                        ; -> 12 (as expected)
*p = #Null

ChangeCurrentElement(lst(), *p)
Debug @ lst()                      ; -> 7998400 in my test (How is that possible???)
Debug lst()                        ; -> 15                 (How is that possible???)
Et cetera is my worst enemy
User avatar
STARGÅTE
Addict
Addict
Posts: 2067
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: ChangeCurrentElement()

Post by STARGÅTE »

@Little John:

For speed optimization DeleteElement() doesn't delete the memory of the element or its content,
it just changes the links for next and previous element.
For speed optimization ChangeCurrentElement() doesn't check the pointer whether it is valid.

Thats a nice feature of Pure Basic linked List and not a bug.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: ChangeCurrentElement()

Post by mk-soft »

Make sure the element is still there.

Code: Select all

;-TOP

; List Managment by mk-soft 

EnableExplicit

Structure udtMyList
  refCount.i
  iVal.i
EndStructure

Global MutexMyList = CreateMutex()

Procedure GetListElement(List MyList.udtMyList())
  LockMutex(MutexMyList)
  MyList()\refCount + 1
  UnlockMutex(MutexMyList)
  ProcedureReturn @MyList()
EndProcedure

Procedure FreeListElement(List Mylist.udtMyList(), *ppMyList.Integer, Delete = #True)
  Protected *pMyList.udtMyList
  LockMutex(MutexMyList)
  If *ppMyList\i
    *pMyList.udtMyList = *ppMyList\i
    If *pMyList\refCount > 0
      *pMyList\refCount - 1
      If *pMyList\refCount = 0 And Delete = #True
        If @Mylist() = *pMyList
          DeleteElement(Mylist())
        Else
          PushListPosition(MyList())
          ChangeCurrentElement(Mylist(), *pMyList)
          DeleteElement(Mylist())
          PopListPosition(Mylist())
        EndIf
      EndIf
    EndIf
    *ppMyList\i = 0
  EndIf
  UnlockMutex(MutexMyList)
EndProcedure

Procedure DeleteListElement(List MyList.udtMyList())
  LockMutex(MutexMyList)
  If MyList()\refCount = 0
    DeleteElement(MyList())
  EndIf
  UnlockMutex(MutexMyList)
EndProcedure

Global NewList MyData.udtMyList()

AddElement(MyData())
MyData()\iVal = 1
AddElement(MyData())
MyData()\iVal = 2
AddElement(MyData())
MyData()\iVal = 3
AddElement(MyData())
MyData()\iVal = 4


SelectElement(MyData(), 2)
Debug "Get Pointer A"
Define *a.udtMyList = GetListElement(MyData())
Debug "Get Pointer B"
Define *b.udtMyList = GetListElement(MyData())
Debug "Get Pointer C"
SelectElement(MyData(), 1)
Define *c.udtMyList = GetListElement(MyData())

ForEach MyData()
  Debug "refCount = " + MyData()\refCount + " | Value = " + MyData()\iVal
Next

Debug "Free Pointer A"
FreeListElement(MyData(), @*a)
ForEach MyData()
  Debug "refCount = " + MyData()\refCount + " | Value = " + MyData()\iVal
Next

Debug "Free Pointer B"
FreeListElement(MyData(), @*b)
ForEach MyData()
  Debug "refCount = " + MyData()\refCount + " | Value = " + MyData()\iVal
Next

Debug "Free all unused ListElements"
ForEach MyData()
  DeleteListElement(MyData())
Next
ForEach MyData()
  Debug "refCount = " + MyData()\refCount + " | Value = " + MyData()\iVal
Next

Debug "Free Pointer C"
FreeListElement(MyData(), @*c)
ForEach MyData()
  Debug "refCount = " + MyData()\refCount + " | Value = " + MyData()\iVal
Next
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
Little John
Addict
Addict
Posts: 4519
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: ChangeCurrentElement()

Post by Little John »

@STARGÅTE:

Yes, I see now.
I previouly believed that PureBasic would keep internally an inventory of pointers which a valid for a particular list. As freak explained this is not the case. So I do understand why ChangeCurrentElement() behaves the way it currently does.
Post Reply