Skip to main content

ABAP Bugs and peculiarities


Some of the design decisions in the ABAP language are a leap backwards when the intention was to leap at best sideways to thrust us into the meaningless paradigm of the now-defunct world of 4GL languages.

ABAP is a horrible language on all counts. Syntax-wise and how it is implemented, but here are just some of the succinct little tidbits I have found and ways to try and circumvent them.

1. Divide by zero is OK! sometimes...

So X / 0 in my opinion is never OK. When X != 0, the result is +-Infinity and for X = 0 the result is undefined. Both should result in an error. Well, for some reason ABAP decided 0 / 0 = 0. Without blinking an eyelid. Well done.

To fix this, and create an exception in all cases of X and Y in expression X / Y, re-write it as:

X / Y -> ( X * ( 1 / Y ) )

The same problem happens with modulus, however the solution is not as elegant:

X mod Y -> ( ( 1 mod Y ) * 0 + X / Y ) )

2. float parsing on older system fail when assigned to a non-F variable!

On pre-702 systems (where there are no DECFLOATS either) the following results in an error:

l_packed = '1e-1'.

The problem is that it expects a simple decimal numeric representation, but instead finds a character 'e' in the text. The solution is to assign it to a simple temporary float variable, and then assign it to the packed. For this purpose one can just create a global static float someplace since it is very temporary (unless two floats need to be parsed at the same time. However this can be slow and cumbersome, and then also has the problem of working with multiple values in a single expression.

A better solution is to also use a R/O global float and assign it the value of 1. And then to rewrite the literal float values as:

l_packed = ( cl_global_class=>s_float_unity * '1e-1' ).

3. Unary negation and implied whitespace-imposed precedence.

Take care, in ABAP:

-1 * 3 ** 2 = -9 , and
-3 ** 2 = 9 , BUT

- 3 ** 2 = -9

Almost (but not quite) as bad an idea as spacing in Python that changes meaning. Wow.

4. Problems with CHANGING any via a char1


On older unpatched systems the following program dumps:
    
REPORT zerror_test.
*-------------------------------------------------------*
CLASS cl_test DEFINITION.
  PUBLIC SECTION.
    METHODS method_true RETURNING value(r_val) TYPE flag.
    METHODS execute CHANGING c_result TYPE any.
ENDCLASS.
*
CLASS cl_test IMPLEMENTATION.
  METHOD method_true.
    " This only dumps with returning C1 (int + strings are OK) 
    " Thus it could be a unicode/utf-8 underlying string issue?
    r_val = 'X'.
  ENDMETHOD.
  METHOD execute.
    " Assigning here to 'X' instead works in all cases:
    c_result = method_true( ).
  ENDMETHOD.
ENDCLASS.
 
START-OF-SELECTION.
DATA: lcl_test TYPE REF TO cl_test.
CREATE OBJECT lcl_test.

" this works:
DATA: lr_result TYPE REF TO data.
FIELD-SYMBOLS:  TYPE any.
CREATE DATA lr_result TYPE string.
ASSIGN lr_result->* TO .
lcl_test->execute( CHANGING c_result =  ).
WRITE :/ .

" this works as well
DATA: l_result TYPE string.
l_result = lcl_test->method_true( ).
WRITE :/ l_result.

" this does not work:
ASSIGN l_result TO .
lcl_test->execute( CHANGING c_result =  ).
WRITE :/ .

" this does not work:
lcl_test->execute( CHANGING c_result = l_result ).
WRITE :/ l_result.
      

5. "Emulating" XOR

Ok, so ABAP does not have XOR, but fortunately there is a way to emulate it. What's also a good thing (luckily) is that XOR does not have shortcut boolean evaluation rules like OR and AND.

The only problem is that the best solution is dependent on the SAP RELEASE:

a XOR b :

On: RELEASE >= 720:
  NOT a EQUIV b ).

And on SAP RELEASE < 720:
  ( OR AND NOT OR NOT )

And the following commutative rules apply for XOR:
   a XOR b XOR c <==> ( XOR b ) XOR c

In summary:

1) and 3) above are fundamental flaws and will not and cannot be fixed lest almost all applications start dumping and/or give different results. But 2) and 4) can (and has) been fixed in newer releases.


Comments

Popular posts from this blog

My Custom Mechanical 60% Keyboard Build

My Custom Mechanical 60% Keyboard Build All the parts   1x GH60 (Satan) board - $35 61x Cherry Clear switches  - $35 2x Cherry Blue switches - $3 10x Cherry Red switches - $10 1x PCB Stabilizer set (6.25 space) - $6 1x Royal Oak Glam 60% case (Black Walnut) - $78 1x Aluminium 60% plate - $19 1x SA profile Choclatier keycaps - $102 ( base, modifiers, and novelties ) 1x Braided Nylon USB cable - $15 Solder, Tools, Risers, Labor, etc. Total: ± $300 (Other single switch types added as needed) Testing the board I had my helper do the work here. We needed to test the board before applying any solder. Assembling Add the stabilizers first Add the plate (using a few switches as spacers) Then add the rest Solder solder solder... And test again: The casing The casing I received did to have built-in risers: So I added my own: Then Assemble (using temporary spare GMK Carbon Cherry-profile k...

Compacting internal memory of SAP tables in ABAP.

How to force-free memory from deleted entries in internal tables in SAP ABAP, since the garbage collector won't touch these. This is only needed in rare occasions and/or when memory fragmentation needs to be avoided. This method will do it fast, and correctly: CLASS cl_demo DEFINITION . PUBLIC SECTION . CLASS - METHODS compact CHANGING ct_tab TYPE ANY TABLE . ENDCLASS . CLASS cl_demo IMPLEMENTATION . METHOD compact . FIELD-SYMBOLS : <lt_buffer> TYPE ANY TABLE , <lt_buffer_std> TYPE STANDARD TABLE , <ls_buffer> TYPE any , <ls_buffer_prev> TYPE any . DATA : ltr_buffer TYPE REF TO data , lsr_buffer TYPE REF TO data , l_kind TYPE c LENGTH 1 . " simple case: IF ct_tab IS INITIAL . FREE ct_tab . RETURN . ENDIF . CREATE DATA ltr_buffer LIKE ct_tab . DESCRIBE TABLE...

Lock Screen on Mac OS X using keyboard shortcut.

1. Download "Global Hotkey" 2. Create a folder "Global Hotkey" and copy contents of downloaded DMG to that. 3. In a terminal do: cd "/Applications/Global Hotkey" ln -s /System/Library/Frameworks/ScreenSaver.framework/Versions/A/Resources/ScreenSaverEngine.app "command f10" 4. Make sure Screensaver is set to prompt for password (you may need to relog for this to take effect) 5. Preferences -> Accounts -> -> Login Items : Add "Global Hotkey.app" 6. Launch the app as well