CALL and CANCEL vs. Invoke and ?

In traditional COBOL, if a Menu program (or say "PROGA") CALLs a sub-program (or say "PROGB") and doesn't CANCEL it upon return, the next time it CALLs it, PROGB may have its variables in the state that they were in - left over from the earlier CALL, instead of being in their initial state (let's ignore the INITIAL key word for this discussion).  My understanding is that most all the time this type of situation can result in hard-to-debug-and-maintain programs and that the general recommendation is to always follow a CALL with a CANCEL and design the subprograms accordingly (i.e., don't ever use this as a "feature").

OK, but what about Managed non-procedural programs (classes) using WinForms or WPF and such?  These are not being CALLed; they are being INVOKEd, right?  Is there an equivalent of a CANCEL that we should be doing after it returns to the INVOKEing program?


  • Verified Answer

    Hi Austin,

    Many programs do depend on COBOL subprograms that are being called to be in their last used state each time they are called. This not only retains the values of the data items in working-storage but also retains the state of open files, etc,

    As you state this behavior can be altered by using CANCEL or the IS INITAL phrase in the PROGRAM-ID.

    For objects this is a bit different. Since you are creating the objects yourself using the "new" constructor, each instance of the object has its own set of data and state. If the data items are defined in the working-storage section of the class then this data will exist for the lifetime of the object and can be shared by all methods of the class or by nested classes and can also be inherited by subclasses. You can also define these data items as static which means that they actually belong to the class itself and not any one instance and so can be shared amongst instances.

    There are also several access modifiers that can be used to control the visibility of data or methods such as public, private, protected, etc.

    If you define data items within a method instead of within the working-storage section of a class then those data items are in the local-storage section of that method and they exist only during the lifetime of that method. Each time the method is called a new copy of the local-storage data items will be created.

    So if you have something like the following:

          class-id MyClass.
          working-storage section.
          01 obj-data binary-long value 0.
          method-id addOnetoData.
          local-storage section.
          01 loc-data binary-long value 0.
          procedure division.
              add 1 to obj-data, loc-data

    If you invoke this method twice then obj-data = 2 while loc-data = 1 after the add statement.

    When dealing with managed objects you don't really have a cancel type statement. If you want the object to be initialized the you would just create a new object. When objects no longer have any references to them within scope the garbage collector will handle the destruction of these objects.

    In the following:

              declare myobj as type MyClass = new MyClass
              invoke myobj::addOnetoData
              set myobj to new MyClass
              invoke myobj::addOnetoData

    The declare statement assigns a new instance of the class MyClass to the object reference myobj. All methods invoked on myobj at this point will be to that same copy of the object.

    In the set statement I am assigning a new instance of the class MyClass to the object reference myobj. The previous object that was referenced no longer has a reference to it so it is a candidate for garbage collection.

    I am really over-simplifying this explanation here as this is really quite an involved topic.

    You might want to review our Webinar series on OO Programming which can be found here:

    I hope this helps answer your question.