Hello everyone, I can not understand what's the matter, why it displays an error.

There is a cyclic dynamic sheet. element [value, reference]

The latter indicates the beginning of the cycle, not nil.

I am trying to remove, but throws out the "invalid Pointer 204". Sat, watched - removal is executed for some reason 2 times, then throws out an error.

Functions are commented, I think it will be clear.

Here is the source .

Here is the delete function itself:

... {DELETE ALL ELEMENTS OF LIST} procedure DeleteList; var p: TPoint; begin repeat begin if BeginList^.Next = BeginList then begin dispose(BeginList); BeginList := nil; break; end else begin p := BeginList; BeginList := BeginList^.Next; dispose(p); end; end; until BeginList = nil end; ... 

    2 answers 2

    The code itself (by reference) did not look, but I think this is not necessary ( even though I worked with memory in pascal 10 years ago ).

    A couple of questions, the answers to which will help you find your error.

    First question:

     if BeginList^.Next = BeginList then 

    Do you save a BeginList somewhere? I doubt because look below and see:

     BeginList := BeginList^.Next; 

    On the first line a couple more questions . What does this line literally mean? Do you update BeginList ^ .Next somewhere? Or do you have to update it yourself?

    The third question What happens to the link, if you delete the object to which it refers?

    These questions are already in principle sufficient. See:

    1. BeginList: = BeginList ^ .Next - you changed BeginList, and with it changed BeginList ^ .Next. If they are not equal initially and you do not change the Next link for objects anywhere, then the condition BeginList ^ .Next = BeginList does not make sense, since always false.
    2. if BeginList ^ .Next = BeginList then - this line just says - if the current object refers to itself, which is not correct in your case, since already wrote why.
    3. You deleted an object (caused dispose). What happened to the link? It still refers to the section of memory, but at this address there are no objects. For good when deleting an object, you should do Next = nil for all objects for which Next referred to a remote object.
    4. And therefore the problem you have in the following - you deleted the first link. Walked through all, and then again trying to remove the first link. After all, Next still refers to this area of ​​memory. And since you didn’t perform any other actions, BeginList ^ .Next = BeginList will almost always be false (when I’ve written the truth).

    As a result, we obtain:

    1. You need to know when to stop. You can save the current value, move forward and start deleting all items. Then your code should work (if you, of course, change the first check to our saved value)
    2. You can do without saving: we are on the current element. Remove the next (!). But before deleting, we change the current NEXT link to the NEXT link of the element to be deleted. With this approach, your initial condition will work as expected, because removing the penultimate element we will refer to ourselves.

    @Shrek , lists can be unidirectional, for example, they can implement a queue or a stack. In cyclic lists, the link to the last element is also not very necessary, because going ahead, I still get it. The only thing - with her convenience more.

    • Here, I did not begin to paint, but the idea is the same :) Yes, it can be done one way, but when you can crawl back and forth it is more convenient. - Artem
    • Damn guys stupid hard. With the error of BeginList, that he pointed to himself constantly saw with a shrek, it became sad :) Now it seems to have fixed it, according to the theory it should work, but no. var p, List: TPoint; begin list: = BeginList; repeat begin writeln ('iteration'); if List ^ .Next = BeginList then begin dispose (BeginList); BeginList: = nil; break; end else begin p: = List; List: = p ^ .Next; dispose (p); end; end; until BeginList = nil end - belka
    • Well, again ... Try to repeat what the compiler should do on paper, if in your head you can not perform these actions ... The first step is to set a reference to the current element. Then delete it and all subsequent ones. In the last step, you are trying to delete an item that has already been deleted. I wrote - installed the link - moved forward and only then deleted. Well, either instead of the last removal, just exit the procedure. And yet - if List ^ .Next = BeginList then - only the next item is deleted. And the current remains in memory - a typical leak. - BOPOH
    • "Well, either instead of the last removal, just exit the procedure." - i.e. delete the current item (which is a List, not a BeginList) and exit, otherwise - the leak that was written above. And yet - somehow from childhood I got used to nullify links when destroying elements. Maybe not critical, but it's easier for me. And it would be easier for you - to implement the procedure for deleting one element at a time, the procedure for moving to the next element, etc. Then it would work with the list and its elements, and not with memory - the first step on the way to the PLO, so to speak. - BOPOH
    • Hehehe ... And you know that you have to swear not to delete an element, but to PushAfter? This is first, and secondly - on GetCount. Why all? repeat count: = count + 1; List: = List ^ .Next; until (List = BeginList); This is from GetCount. If the list is not empty - everything is OK, but what if it is empty? List: = List ^ .Next; will immediately crash with an error ... begin p ^ .Value: = value; p ^ .Next: = BeginList; ... end This is from PushAfter. What is p? The compiler does not know, and you are trying to derefend this "something" ... Well, plus the jambs with the removal, do not forget to fix it. - BOPOH

    The latter indicates the beginning of the cycle, not nil.

    But this is wrong. The latter must go to null by the rules. Read again about the dynamic arrays on pascal.

    The fact is that no one does. because unnecessary actions appear when deleting / adding the first / last elements. it is not good.

    It is better to revise this structure.

    Instead of that it seems that initially it is necessary to set initial value for next.

     if BeginList^.Next = BeginList then 

    And not just to take and make a condition?

    and then find out the next value of next and only then delete the element, then repeat the operation until the moment until next! = null and in your case an error will creep out you will delete the first element, and the last element has nowhere to refer to; it will never find the very first element.

    And from this the conclusion and error display.

    Shl, the code looked - it's hard.

    The dynamic list must have at least 3 values

    1. This is the value itself (be it a variable, an array, a string, etc.)
    2. previous item reference
    3. link to the next item

    In the code there is only a link to the next list item and value.

    Otherwise, this is some strange list, well, at least for me, so if you do something right.

    • I know this is how a regular list should end. And this one, as I indicated, is “cyclical,” that is, its end indicates the beginning. - belka
    • UPDATE # 2: Another such question, if the problem is in the last element, why does the error take off after the 2nd cycle? Elements then I added 6 pieces. - belka
    • one
      And you take a pen / pencil. And on a piece of paper, step by step add all the elements, and then on your code, try to delete them, well, or use the built-in step-by-step execution in pascal. He will show you everything and do not forget the output of variables to do, you will see what the joint is. ps> why does the error take off after the 2nd cycle? most likely not after the second pass, but after the 2nd iteration, going through this means going completely through the cycle. - Artem
    • I apologize, I mean the iteration. Now I check, unsubscribe immediately. - belka