COBOL und 2.020 $ 202.02

In den vergangenen Jahren, sogar in den letzten ein oder zwei Jahren, stieß ich manchmal auf die Nachricht, dass jemand eine Rechnung oder einen Scheck über einen lächerlichen Betrag von 2.020.202 Dollar erhalten hatte ... und 02 Cent.



Wenn Sie dies sehen, handelt es sich (mit ziemlicher Sicherheit) um einen COBOL-Programmierfehler. Die meisten COBOL-Programmierer machen diesen dummen Fehler, und ich bin keine Ausnahme.



Das Problem wird durch die Art und Weise verursacht, wie wir den Datensatz normalerweise initialisieren. Nehmen wir ein kleines Programm wie dieses:



       identification division.
       program-id.
           mistake.
       
       data division.
       working-storage section.
      
      * *** Input record, typically maintained on disk/tape somewhere.
       01  dr-datarec.
           03  dr-name                 pic x(20).
           03  dr-amount               pic s9(7)v99, comp-3.

      * *** print record, sent to a line printer.
       01  dt-detail.
           03  dt-name                 pic x(20).
           03  filler                  pic x.
           03  dt-amount               pic z,zzz,zz9.99.            
       
       procedure division.
       
           move spaces                 to dr-datarec.
           move "test"                 to dr-name.
           move 100                    to dr-amount.

           move spaces                 to dt-detail.
           move dr-name                to dt-name.
           move dr-amount              to dt-amount.

           display dt-detail.
       
           stop run.


In diesem Programm der Eingabedatensatz dr-datarec. Normalerweise kommt es von irgendwo auf der Festplatte, aber für diesen einfachen Test wird es manuell erstellt.



Sobald ein Eingabedatensatz empfangen wurde, wird die Berechnung durchgeführt und dann wird der Datensatz mit ausgegeben dt-detail.



Das Problem ist, wie der Datensatz erstellt wird dr-datarec. Beachten Sie, wie die Leerzeichen verschoben werden, um sie zu initialisieren. Dies war die typische Methode zum Initialisieren eines Datensatzes.



Somit gibt es in allen Bereichen von PIC X Leerzeichen. Aber! Alle COMP-3-Felder werden ebenfalls initialisiert, jedoch nicht auf Null. Der Programmierer muss sicherstellen, dass für alle COMP-3-Felder gültige Werte generiert werden. Das Testprogramm macht es richtig:



           move spaces                 to dr-datarec.
           move "test"                 to dr-name.
           move 100                    to dr-amount.


Es sind dr-amounteindeutig 100 auf dem Feld. Nach dem Start stellt sich heraus:



./mistake 
test                       100.00


Was ist, wenn ein Codierungsfehler vorliegt und der Datensatz dr-amountnicht ordnungsgemäß initialisiert wurde?



Es gibt dort noch ASCII-Leerzeichen. Dies ist ein Hexadezimalwert von 20 oder binär 0010 0000.



COMP-3 speichert Ziffern als Vier-Bit-Halbbytes, sodass ein Leerzeichen als 20 angezeigt wird. Wenn Sie 9 Ziffern wie dr-Betrag haben, sind 10 Speicher-Halbbytes (9 Halbbytes) erforderlich für Ziffern und eine für Vorzeichen) oder 5 Bytes.



Das Verschieben von Leerzeichen dr-datarecführt dazu, dass 5 Leerzeichen oder der Hexadezimalwert 2020202020 in diesem Feld gespeichert werden. Wenn Sie versuchen, eine nicht initialisierte Variable zu verwenden, wird diese als 2020 202.02 interpretiert.



Wenn Sie die Initialisierung auskommentieren dr-amount, können Sie diesen Fehler erzwingen:



           move spaces                 to dr-datarec.
           move "test"                 to dr-name.
     *     move 100                    to dr-amount.


Jetzt beim Starten des Programms:



./mistake 
test                 2,020,202.02


Um dieses Problem zu beheben, führte COBOL 85 das Verb INITIALIZE ein. Anstatt Leerzeichen in einen Datensatz zu verschieben, initialisieren Sie ihn und es werden Leerzeichen in alphanumerische Felder und Nullen in numerische Felder verschoben:



      *    move spaces                 to dr-datarec.
           initialize dt-detail.
           move "test"                 to dr-name.
      *    move 100                    to dr-amount.


Ausführungsergebnis:



./mistake 
test                         0.00


Wenn Sie also das nächste Mal eine arme Witwe sehen, die eine Stromrechnung über 2.020.202,02 USD erhalten hat, wissen Sie genau, was passiert ist!



All Articles