Menu

#76 CLIPS crashes when global variable modified

1.0
new
nobody
None
2024-07-24
2024-07-13
xyando
No

Hello,

The following commands makes CLIPS to crash.

$ ./clips -f globalbind.bat
CLIPS (6.4.2 5/7/24)
CLIPS> (defglobal ?foo = (create$ 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0))
CLIPS> (defglobal ?bar = (create$ 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0))
CLIPS>
(deffunction test (?foo ?bar)
(loop-for-count 10 do
(bind ?foo ?foo)
(bind ?bar ?bar)
)
(printout t "FOO " ?foo crlf)
(printout t "BAR " ?bar crlf)
)
CLIPS>
(test ?foo ?bar)

[PRNTUTIL3]
*** CLIPS SYSTEM ERROR ***
ID = EVALUATN7
CLIPS data structures are in an inconsistent or corrupted state.
This error may have occurred from errors in user defined code.


The patch attached seems to fix this problem.
Thanks.

1 Attachments

Discussion

  • xyando

    xyando - 2024-07-13

    The posted comment is erroneous because the asterisks are missing.
    Please refer the attached file.

     
  • xyando

    xyando - 2024-07-14

    The revised patch is attached because the elder patch fails CLIPS test_suite.

     
  • Gary Riley

    Gary Riley - 2024-07-16

    A fix has been checked into the svn repository. The issue occurs when setting the current value of a defglobal to its current value. This can cause the value to be prematurely released. The bug can occur outside the body of a deffunction, so the proposed patch won't fix the issue for all cases.

             CLIPS (6.4.1 4/8/23)
    CLIPS> (defglobal ?*foo*  = (create$  0.0))
    CLIPS> 
    (loop-for-count 1 do
       (bind ?*foo* ?*foo*))
    [ARGACCES2] Function 'loop-for-count' expected argument #3 to be of type integer, float, symbol, string, instance name, instance address, fact address, external address, or multifield.
    FALSE
    CLIPS> 
    
     
    • xyando

      xyando - 2024-07-17

      Thanks Gary,
      but I think an additional modification is necessary(see attached patch)
      because the following program results an endless looping.

      (defglobal ?*x* = (create$ 1 2 3))
      (deffunction test()
        (while TRUE do
          (bind ?*x* (rest$ ?*x*))
          (printout t ?*x* crlf)
          (if (= (length$ ?*x*) 0) then
            (break)
          )
        )
      )
      
       
      • Gary Riley

        Gary Riley - 2024-07-17

        Nice catch. I checked in an update.

         
        • xyando

          xyando - 2024-07-21

          Thanks Gary,
          The endless looping is resolved. But the globalbind.bat fails again.

          I think the equality checking once you have added is still necessary
          (but after NormalizeMultifield(), but before displaying watch info)
          to avoid premature release.

           
          • Gary Riley

            Gary Riley - 2024-07-22

            I checked in a fix. I forgot to test the original issue. There are multiple ways to generate a bug with this issue and just modifying QSetDefglobalValue won't fix all of them. Here's an example which globalbind-3.patch will still generate an error:

            (defglobal ?*foo* = (create$ 0.0))
            
            (deffunction test (?foo)
               (bind ?*foo* ?foo)
               (println ?foo)
               (bind ?*foo* (create$ 3.0))
               (println ?foo))
            (test ?*foo*)
            

            What I did to resolve the issue is modify the routines which return the value of the global variable to return a copy of the multifield value instead of the value stored directly in the global. This preserves the multifield until garbage collection kicks in at the appropriate time.

             
            • xyando

              xyando - 2024-07-24

              It all works fine. Thanks.

               

Log in to post a comment.