Page 1 of 1

ChangeCurrentElement()

Posted: Sat Aug 03, 2019 11:39 am
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???)

Re: ChangeCurrentElement()

Posted: Sat Aug 03, 2019 12:44 pm
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.

Re: ChangeCurrentElement()

Posted: Sat Aug 03, 2019 12:46 pm
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???)

Re: ChangeCurrentElement()

Posted: Sat Aug 03, 2019 2:13 pm
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.

Re: ChangeCurrentElement()

Posted: Sat Aug 03, 2019 2:27 pm
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

Re: ChangeCurrentElement()

Posted: Sat Aug 03, 2019 2:33 pm
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.