Skip to Content
Author's profile photo Horst Keller

Invalid References in Reference Variables

What an interesting chain of events: In the new SAP Community all my old blog posts from SDN – the predecessor of SCN (R.I.P.) – are visible again (they were buried in SCN). Now people start looking at those and also ask questions. One question is about handling of invalid references and – dang! – a gap in the documentation was unveiled.Let’s fill the gap.

References in reference variables normally are either initial or point to objects.

 

  • For a valid reference, pointing to an object, the predicates IS NOT INITIAL and IS BOUND are both true.
  • An initial reference variable contains the null reference and the predicates IS INITIAL and IS NOT BOUND are true.

Besides those there can be also non initial invalid reference variables for which the predicates IS NOT INITIAL and IS NOT BOUND are true. How can you create invalid references?

Example 1, references pointing to deleted table lines:

DATA itab TYPE TABLE OF i WITH EMPTY KEY.
itab = VALUE #( ( 1 ) ( 2 ) ( 3 ) ).
DATA(dref) = REF #( itab[ 2 ] ).
DELETE itab INDEX 2.
BREAK-POINT.

The debugger says for dref: FREED ITAB:{A:1*\TYPE=I}.

Example 2, references pointing to deleted stack objects:

CLASS cls DEFINITION.
  PUBLIC SECTION.
    CLASS-DATA dref TYPE REF TO i.
    CLASS-METHODS main.
ENDCLASS.

CLASS cls IMPLEMENTATION.
  METHOD main.
    DATA number TYPE i.
    dref = REF #( number ).
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  cls=>main( ).
  BREAK-POINT.

The debugger says for cls=>dref: FREED STACK:{A:1*\TYPE=I}.

Unfortunately the behavior of such invalid references was not fully described until now. In fact it is quite similar to the behavior of initial null references:

 

  • For non initial invalid references as well as for initial references the predicate IS BOUND is false.
  • You cannot access objects via non initial invalid references or initial references (that’s trivial).

Interestingly enough, you can assign non initial invalid references as well as initial references to any reference variable using down casts. The reason is, that those references don’t have a dynamic type that can be checked.

But there is one difference. While the initial null reference can be compared to valid references (and is always smaller), non initial invalid references cannot be compared with any other references. There is no sort order defined for non initial invalid references. Any attempt to compare a non initial invalid reference leads to a runtime error SYSTEM_DATA_ALREADY_FREE.

DATA itab TYPE TABLE OF i WITH EMPTY KEY.
itab = VALUE #( ( 1 ) ( 2 ) ( 3 ) ).
DATA(dref) = REF #( itab[ 2 ] ).
DELETE itab INDEX 2.

DATA ref TYPE REF TO data.
IF dref = ref. "<- Crash!
ENDIF.

What you can use is:

IF dref IS NOT INITIAL AND
   dref IS NOT BOUND.
ENDIF.

That you cannot compare non initial invalid references has an important impact on internal tables containing columns of references (and that was the question)! If an internal table contains non initial invalid references any table operation that involves comparisons of those will lead to the above runtime error. That concerns WHERE conditions, sortings, access via sorted keys, …

DATA itab TYPE TABLE OF i WITH EMPTY KEY.
itab = VALUE #( ( 1 ) ( 2 ) ( 3 ) ).
DATA(dref) = REF #( itab[ 2 ] ).
DELETE itab INDEX 2.

DATA rtab TYPE TABLE OF REF TO i WITH EMPTY KEY.
APPEND dref TO rtab.
APPEND INITIAL LINE TO rtab.
SORT rtab BY table_line. "<- Crash!

Now the question arises, wouldn’t it make sense to define a sort order for non initial invalid references? Currently, the answer is no (sorry Former Member). Why? Because any time a reference variable becomes invalid, e.g. when leaving a procedure, each internal table that contains the reference variable as part of a sorted key must then be reorganized. Or with other words, the internal organization of internal tables must react on non internal table statements. And that is not wanted.

Seen from this angle, one can say that it is not the best idea to declare sorted keys that contain reference variables as key fields.

DATA itab TYPE SORTED TABLE OF REF TO data
          WITH NON-UNIQUE KEY table_line.

DATA jtab TYPE STANDARD TABLE OF REF TO data
          WITH NON-UNIQUE SORTED KEY ref COMPONENTS table_line.

Usage of those can lead to unexpected runtime errors if non initial invalid references are involved.

To prevent such runtime errors, you can use:

DELETE itab WHERE table_line IS NOT BOUND.

PS: Maybe it would be better, if there wasn’t a sort order for references at all and reference variables wouldn’t be alllowed as key fields of internal tables.

Assigned Tags

      7 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member

      Hi Horst,

      Thanks for highlighting this trapdoor.

      Throughout the blog you have mentioned reference variables as initial non initial. Would it not be better to refer them instead as boundunbound?

      BR,
      Suhas

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Nope!

      So I made it not clear. ?

      An initial reference variable is always unbound (but not invalid so to say). This blog is mainly about non initial reference variables that are unbound. Those were bound once but became invalid.

      Author's profile photo Jerry Wang
      Jerry Wang
      Hello Horst,
      You Rock!! I have found the report DEMO_IS_NOT_BOUND you write in our internal system under package SABAPDEMOS,and I also found other 593 reports there. Those demo reports are really helpful for we application developers, thank you very much for your great job!
      And your blog does contain a thorough summary of possible scenarios where invalid reference can occur, great article! Unfortunately I didn't read it before I write my own: IS BOUND, IS INITIAL and IS ASSIGNED. In my blog I consider the NOT BOUND AND NOT INITIAL reference as Dangling Reference in computer science. What do you think? And I also add a small part of IS ASSIGNED for field symbol. Feel free to leave your comment if you find anything misleading or incorrect there. Thanks a lot!
      Best regards,
      Jerry

       

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      These are the source codes of the ABAP keyword documentation’s example library. Normally you should access those from the documentation where they are located in a context. The ABAP keyword documentation has two kinds of examples: part of the text (but also syntax checked for copy and paste) and those loaded from the example library.

      Author's profile photo Chaouki Akir
      Chaouki Akir

      In a program, is it possible to have an object NOT INITIAL and NOT BOUND ?

      REPORT ddd.
      
      * Is the global data go can be "NOT INITIAL" and "NOT BOUND" ?
      
      CLASS lcl_tmp DEFINITION.
      ENDCLASS.
      CLASS lcl_tmp IMPLEMENTATION.
      ENDCLASS.
      
      DATA go TYPE REF TO lcl_tmp.
      
      *data gref type ref to data.
      
      IF go IS BOUND.
        IF go IS INITIAL.
          WRITE / 'go is bound and initial'.
        ELSE.
          WRITE / 'go is bound and not initial'.
        ENDIF.
      ELSE.
        IF go IS INITIAL.
          WRITE / 'go is not bound and initial'.
        ELSE.
          WRITE / 'go is not bound and not initial'.
        ENDIF.
      ENDIF.
      
      
      PERFORM get_lo CHANGING go.
      
      IF go IS BOUND.
        IF go IS INITIAL.
          WRITE / 'go is bound and initial'.
        ELSE.
          WRITE / 'go is bound and not initial'.
        ENDIF.
      ELSE.
        IF go IS INITIAL.
          WRITE / 'go is not bound and initial'.
        ELSE.
          WRITE / 'go is not bound and not initial'.
      *
      *  !!! is it possible ?
      *
        ENDIF.
      ENDIF.
      
      
      FORM get_lo CHANGING po TYPE REF TO lcl_tmp.
        DATA lo TYPE REF TO lcl_tmp.
      
      
        CREATE OBJECT lo.
      *  get REFERENCE OF lo into gref.
      
        po = lo.
        FREE lo.
      ENDFORM.
      

       

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      I guess you mean object reference variables when saying object.

      No.

      See note under IS BOUND

       

      Author's profile photo Sandra Rossi
      Sandra Rossi

      NOTE: for a DATA reference, the condition NOT INITIAL and NOT BOUND may be true.