Page 1 of 1
Linked list pointer trouble
Posted: Fri Feb 16, 2007 1:06 am
by JJ
Hi,
I study the answer made to Uvosa by Fred (
http://www.purebasic.fr/english/viewtop ... inked+list) and I believe that a trouble exist in the PB 4.02 with linked list and pointer.
Code: Select all
Structure TestStruct
Text.b[10000]
EndStructure
Procedure SetStructList(val, *Test.TestStruct())
AddElement(*Test())
; Uncomment the following line(s) to see memory reserved twiced (use the task manager to see the trouble)
; 100 MB reserved when the next line is commented, and it seems normal
; 200 MB reserved when the next line is uncomment, it's the problem
; *Test() = AllocateMemory(SizeOf(TestStruct))
; UnCommented lines produce "Pointer is null." error since PB v4.02, if the previous line is commented
; *Test()\Text[0]=val
EndProcedure
Procedure test()
NewList toto.TestStruct()
CallDebugger
For i=1 To 10000
SetStructList(i%$FF, toto.TestStruct())
Next
CallDebugger
ClearList(toto())
EndProcedure
;- Main
test()
End
Usually if only pointer is reserved for each Addelement(), we must find near 40000 bytes reserved (if all the lines are commented like example) but we have 100MB. It seems that the memory is allocated but the pointer returned is always NULL.
Thanks in advance for your help.
Posted: Fri Feb 16, 2007 11:37 am
by Kaeru Gaman
hi.
if you want to post quicklinks (without URL-tags) you have to leave spaces around them.
(
http://www.purebasic.fr/english/viewtop ... inked+list )
I don't get the point really... not your's but the code's
there seem to be some problems, but where is it exactly....?
my main problem is, that I never used pointer notations to reserve elements.
the memory usage seems to be clear for me.
you add 10000 elements that need 10008 bytes each and surely get them.
if you alter the pointer afterwards to some new allocated memory,
of course the memory usage should double.
but I don't get the point why the pointer to the old allocated mem should be NULL....
maybe the mem is allocated but the pointer to it isn't connected correctly?
additionally just for interest:
what is the advantage in this pointer-notation for using AddElement anyways?
I would use a normal call of AddElement, you can use a pointer access after that in every case....
it's just that...
if the basic idea to use AddElement with a pointer was wrong,
then it's not a bug of PB but a bug in this form of programming....
Posted: Fri Feb 16, 2007 3:16 pm
by pcfreak
even if you define the procedure parameter as pointer, it is handled as linkedlist, thus you can't use it as pointer.
Code: Select all
Structure TestStruct
Text.b[10000]
EndStructure
Procedure SetStructList(val, *Test.TestStruct())
AddElement(*Test())
; Uncomment the following line(s) to see memory reserved twiced (use the task manager to see the trouble)
; 100 MB reserved when the next line is commented, and it seems normal
; 200 MB reserved when the next line is uncomment, it's the problem
; *Test() = AllocateMemory(SizeOf(TestStruct))
; UnCommented lines produce "Pointer is null." error since PB v4.02, if the previous line is commented
*toto.TestStruct=@*Test()
*toto\Text[0]=val
EndProcedure
Procedure test()
NewList toto.TestStruct()
CallDebugger
For i=1 To 10000
SetStructList(i%$FF, toto.TestStruct())
Next
CallDebugger
ClearList(toto())
EndProcedure
;- Main
test()
End
either you use the pointer returned from AddElement (contains the pointer to the element before and after) or you get it directly from the element as shown above. this way you don't have to care about the internal linkedlist management of purebasic. either way the 10000 bytes for the structure are reserved after the AddElement command, hence it grows even more if you allocate it every time additional to it. i don't know if it can be considered as memory leak that purebasic doesn't frees the memory if the pointer gets changed. well, seems a bit confusing how purebasic handles linkedlists passed as pointer. in one point it's as if it wasn't passed as pointer and in one way it's like a pointer ('cause you can't just change the element right after adding a new element, but needs to take the pointer of it)
it's just not obviously how this has to be handles correctly, so i guess it's a problem for the help file (partly for purebasic itself, 'cause it's just too confusing). the more you think about it the less you get, thus that's it from me

Posted: Fri Feb 16, 2007 4:23 pm
by Trond
I don't understand a thing of what you're saying. And what I do understand is wrong.
Linked lists are ALWAYS passed as a pointer to the list.
even if you define the procedure parameter as pointer, it is handled as linkedlist, thus you can't use it as pointer.
You haven't declared a pointer parameter, you have declared a linked list of pointers as the parameter.
Posted: Fri Feb 16, 2007 4:25 pm
by freak
Of course the memory usage grows. You call AllocateMemory() 10000 times, but not one FreeMemory()
pcfreak:
I think you misunderstand this: *Test.TestStruct() defines a linkedlist OF pointers.
So the elements in the list are pointers, not the list itself.
When you call AddElement() on such a list, you get a new empty pointer, just like when defining a variable *Pointer.
You have to assign some memory location to it in order to work with it.
btw, linkedlists as procedure parameters are always passed by reference.
Posted: Fri Feb 16, 2007 4:33 pm
by pcfreak
freak wrote:
pcfreak:
I think you misunderstand this: *Test.TestStruct() defines a linkedlist OF pointers.
So the elements in the list are pointers, not the list itself.
When you call AddElement() on such a list, you get a new empty pointer, just like when defining a variable *Pointer.
You have to assign some memory location to it in order to work with it.
but why are for each element 10000 bytes reserved when it gets created? it 'seems' as if not a pointer but the whole structure gets created, as in my example you can even access this structure. sorry, but i just don't get the system behind that. if i want a list of pointers that can be used on structured memory field by field i would declare it as it was in the example, but that shouldn't allocate the memory for the structure but only a pointer for such.

Posted: Fri Feb 16, 2007 4:39 pm
by freak
You define the original list not as a pointer. This is the problem.
Posted: Fri Feb 16, 2007 8:02 pm
by JJ
Kaeru Gaman wrote:hi.
if you want to post quicklinks (without URL-tags) you have to leave spaces around them.
(
http://www.purebasic.fr/english/viewtop ... inked+list )
I don't get the point really... not your's but the code's
there seem to be some problems, but where is it exactly....?
my main problem is, that I never used pointer notations to reserve elements.
the memory usage seems to be clear for me.
you add 10000 elements that need 10008 bytes each and surely get them.
if you alter the pointer afterwards to some new allocated memory,
of course the memory usage should double.
but I don't get the point why the pointer to the old allocated mem should be NULL....
maybe the mem is allocated but the pointer to it isn't connected correctly?
It's what I think!
additionally just for interest:
what is the advantage in this pointer-notation for using AddElement anyways?
I use it in recursive code, who a linked list is created in each entry call, and i use the pointer on the linked list to work with it.
I would use a normal call of AddElement, you can use a pointer access after that in every case....
it's just that...
if the basic idea to use AddElement with a pointer was wrong,
then it's not a bug of PB but a bug in this form of programming....
Posted: Fri Feb 16, 2007 9:53 pm
by JJ
freak wrote:Of course the memory usage grows. You call AllocateMemory() 10000 times, but not one FreeMemory()
pcfreak:
I think you misunderstand this: *Test.TestStruct() defines a linkedlist OF pointers.
So the elements in the list are pointers, not the list itself.
When you call AddElement() on such a list, you get a new empty pointer, just like when defining a variable *Pointer.
You have to assign some memory location to it in order to work with it.
btw, linkedlists as procedure parameters are always passed by reference.
I agree with you, but if you uncommented the line:
*Test()\Text[0]=val
You will see that in PB 4.01 everything works fine, the linked list is created correctly and you can write the 10000 byte without any problem for each element. And if you do that with PB 4.02, you have an error "pointer null".
In PB4.02 you see the memory reserved growing and never freeing. Then if the linked list contains only pointer, why Pure reserved on each call 10000 bytes and not only the 8 bytes for the pointers.
Second point why the memory are never free when the procedure returns. The allocation is manage dynamiquely by the core of PB, then how could you free the memory allocated by Pure? (leave all the line commented for the test, and try to free the memory)
I didn't verify if in PB 4.01 the memory is properly freeing, I'll make the test when I'm come back from vacation.
PS: I'm in vacation tonight so, i will continue the discussion next Saturday.
Posted: Sat Feb 17, 2007 8:18 am
by Demivec
@JJ
This is how you should be performing the actions you needed:
Code: Select all
Structure TestStruct
Text.b[10000]
EndStructure
Procedure SetStructList(val, Test.TestStruct())
AddElement(Test())
; Uncomment the following line(s) to see memory reserved twiced (use the task manager to see the trouble)
; 100 MB reserved when the next line is commented, and it seems normal
; 200 MB reserved when the next line is uncomment, it's the problem
; *Test() = AllocateMemory(SizeOf(TestStruct))
; UnCommented lines produce "Pointer is null." error since PB v4.02, if the previous line is commented
Test()\Text[0]=val
EndProcedure
Procedure Test()
NewList toto.TestStruct()
CallDebugger
For I=1 To 10000
SetStructList(I%$FF, toto.TestStruct())
Next
CallDebugger
ClearList(toto())
EndProcedure
;- Main
Test()
End
Your procedure SetStructList() is passed a linked list by reference which is not the same as passing a pointer to it. This means the procedure should declare the variable as a linked list type. It should address it the same as a linked list.
The only change necessary to make the correction is to remove the "*" from your variable so that it is not confused with a pointer to a structure (not a linked list as you desired), see comment below. All the comments in SetStructList() are now irrelevant.
In the code you presented it seems the compiler can't tell if it should treat the variable *Test().TestStruct() as a pointer to a linked list, or a generic pointer, or perhaps a pointer to a structure (who knows, maybe Fred?:)). This is evident from the code you first presented. I don't quite understand it but, if you checked the value of the pointer while in the procedure it points to a structure of TestStruct. It can access it but, it seems to treat every element of the structure as a pointer also. The two interpretations run into conflict. For instance, it can't acess things in the structure that have a value of zero and says they have a null pointer. Also, when you reserve memory space for a structure and assign it to the pointer with
Code: Select all
*Test() = AllocateMemory(SizeOf(TestStruct))
it assigns the value of the memory pointer (a Long) to the location pointed to by the structure. I think there is a bug or undesirable feature in the way this value is assigned. It ignores the "structure" format and simply stores the 32 bit value starting at the first memory location. By viewing the value of the structure after this assignment it is shows that the first four entries in the array of bytes were changed. THIS is what I would think is unexpected and an issue to be resolved or avoided.
As stated earlier though, YOUR problem is the misuse of variable types. If you got away with it in the past your luck seems to have run out.
Posted: Sat Feb 24, 2007 3:38 pm
by JJ
Demivec wrote:@JJ
This is how you should be performing the actions you needed:
Code: Select all
Structure TestStruct
Text.b[10000]
EndStructure
Procedure SetStructList(val, Test.TestStruct())
AddElement(Test())
; Uncomment the following line(s) to see memory reserved twiced (use the task manager to see the trouble)
; 100 MB reserved when the next line is commented, and it seems normal
; 200 MB reserved when the next line is uncomment, it's the problem
; *Test() = AllocateMemory(SizeOf(TestStruct))
; UnCommented lines produce "Pointer is null." error since PB v4.02, if the previous line is commented
Test()\Text[0]=val
EndProcedure
Procedure Test()
NewList toto.TestStruct()
CallDebugger
For I=1 To 10000
SetStructList(I%$FF, toto.TestStruct())
Next
CallDebugger
ClearList(toto())
EndProcedure
;- Main
Test()
End
Your procedure SetStructList() is passed a linked list by reference which is not the same as passing a pointer to it. This means the procedure should declare the variable as a linked list type. It should address it the same as a linked list.
The only change necessary to make the correction is to remove the "*" from your variable so that it is not confused with a pointer to a structure (not a linked list as you desired), see comment below. All the comments in SetStructList() are now irrelevant.
In the code you presented it seems the compiler can't tell if it should treat the variable *Test().TestStruct() as a pointer to a linked list, or a generic pointer, or perhaps a pointer to a structure (who knows, maybe Fred?:)). This is evident from the code you first presented. I don't quite understand it but, if you checked the value of the pointer while in the procedure it points to a structure of TestStruct. It can access it but, it seems to treat every element of the structure as a pointer also. The two interpretations run into conflict. For instance, it can't acess things in the structure that have a value of zero and says they have a null pointer. Also, when you reserve memory space for a structure and assign it to the pointer with
Code: Select all
*Test() = AllocateMemory(SizeOf(TestStruct))
it assigns the value of the memory pointer (a Long) to the location pointed to by the structure. I think there is a bug or undesirable feature in the way this value is assigned. It ignores the "structure" format and simply stores the 32 bit value starting at the first memory location. By viewing the value of the structure after this assignment it is shows that the first four entries in the array of bytes were changed. THIS is what I would think is unexpected and an issue to be resolved or avoided.
As stated earlier though, YOUR problem is the misuse of variable types. If you got away with it in the past your luck seems to have run out.
Thank's Demivec for your time and help, you right, now everything is OK. But I think that in the <PB4.01 they was a bug with this type of pointer linkedlist declaration.