BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
rbettinger
Lapis Lazuli | Level 10

Let's say that I write a module in SAS/IML that calls a second module. We can call them eponymously Module1 and Module2 without loss of generality. Let's say that Module 2 receives bad data from Module1 because I did not create good input data for Module 1. Oops! My bad. The IML interpreter complains and displays error diagnostics that reference the point of error in Module1. So far, so good. I find the line of code in Module1 and observe that it invokes Module2. Now, here is where I need help. The error diagnostics indicate that there is an offset point in Module2 that I assume will allow me to find the error in that module.

 

How do I use the information produced for Module2? I see an offset point and traceback information, but I don't know how to determine the line of code in Module2 that corresponds to this offset point. Also, how can I use the traceback information?

TIA,

Ross

1 ACCEPTED SOLUTION

Accepted Solutions
Rick_SAS
SAS Super FREQ

The "offset line' is reported when a module is stored and then loaded in another program. Because modules are stored in compiled form, the error messages are more terse and less understandable when you use a stored module.

 

During the debugging phase, I like to use a %INCLUDE statement or paste the module definitions into my program. then I get the exact line number on which the errors occurs regardless of how many levels deep the modules are nested. For example, look at this program, which creates an error for a module that is defined in the program itself:

proc iml;
start mod1(x); /* Line 1 */
y=1; /* Line 2 */
w=mod2(x); /* Line 3 */
z=2;
sum = x + y + w;
return sum;
finish;

start mod2(x); /* Line 1 */
a=1; /* Line 2 */
b=2; /* Line 3 */
c=log(x); /* Line 4 */
d=4;
return a+b+c+d;
finish;
q1 = mod1(1);
q2 = mod1(-1);  /* create a run time error */

The log is

1    proc iml;
NOTE: Writing HTML Body file: sashtml.htm
NOTE: IML Ready
2    start mod1(x);
2  !                /* Line 1 */
3    y=1;
3  !      /* Line 2 */
4    w=mod2(x);
4  !            /* Line 3 */
5    z=2;
6    sum = x + y + w;
7    return sum;
8    finish;
NOTE: Module MOD1 defined.
9
10   start mod2(x);
10 !                /* Line 1 */
11   a=1;
11 !      /* Line 2 */
12   b=2;
12 !      /* Line 3 */
13   c=log(x);
13 !           /* Line 4 */
14   d=4;
15   return a+b+c+d;
16   finish;
NOTE: Module MOD2 defined.
17   q1 = mod1(1);
18   q2 = mod1(-1);
ERROR: (execution) Invalid argument to function.

 operation : LOG at line 13 column 6
 operands  : x

x      1 row       1 col     (numeric)

        -1

 statement : ASSIGN at line 13 column 1
 traceback : module MOD2 at line 13 column 1
             module MOD1 at line 4 column 1

NOTE: Paused in module MOD2.

From your description, it sounds like you are loading some modules and want to find the offending line in the stored module. To do that, you MUST have access to the original source of the module so that you can count the offset lines. The START statement is Line 1 and the lines increment with each complete statement (basically, count semicolons).  For example, here is the same program, but this time we STORE and LOAD the modules. The error is in a stored module:

 

proc iml;
start mod1(x);      /* Line 1 */
  y=1;              /* Line 2 */
  w=mod2(x);        /* Line 3 */
  z=2;
  sum = x + y + w;
  return sum;
finish;

start mod2(x);      /* Line 1 */
  a=1;              /* Line 2 */
  b=2;              /* Line 3 */
  c=log(x);         /* Line 4 */
  d=4;
  return a+b+c+d;
finish;
store module=(mod1 mod2);
QUIT;

proc iml;
load module=(mod1 mod2);
q1 = mod1(1);
q2 = mod1(-1);
quit;

The log looks like this:

2988  q2 = mod1(-1);
ERROR: (execution) Invalid argument to function.

 operation : LOG at offset   4 column   8
 operands  : x

x      1 row       1 col     (numeric)

        -1

 statement : ASSIGN at offset   4 column   3
 traceback : module MOD2 at offset   4 column   3
             module MOD1 at offset   3 column   3

NOTE: Paused in module MOD2.

The top of the log tells you that the there is an invalid argument to the LOG function and that the argument is the symbol x, which has the value -1.  Many times you can find the error using that information. If not, the next section tells you more. The error is during an assignment statement (c=...) on the 4th line of the MOD2 module, where the START statement is Line 1. The 'column 3' information tells you the location of the equal sign. The error occurs when trying to form the expression to assign to C.

 

Hope this helps. 

View solution in original post

4 REPLIES 4
Rick_SAS
SAS Super FREQ

The "offset line' is reported when a module is stored and then loaded in another program. Because modules are stored in compiled form, the error messages are more terse and less understandable when you use a stored module.

 

During the debugging phase, I like to use a %INCLUDE statement or paste the module definitions into my program. then I get the exact line number on which the errors occurs regardless of how many levels deep the modules are nested. For example, look at this program, which creates an error for a module that is defined in the program itself:

proc iml;
start mod1(x); /* Line 1 */
y=1; /* Line 2 */
w=mod2(x); /* Line 3 */
z=2;
sum = x + y + w;
return sum;
finish;

start mod2(x); /* Line 1 */
a=1; /* Line 2 */
b=2; /* Line 3 */
c=log(x); /* Line 4 */
d=4;
return a+b+c+d;
finish;
q1 = mod1(1);
q2 = mod1(-1);  /* create a run time error */

The log is

1    proc iml;
NOTE: Writing HTML Body file: sashtml.htm
NOTE: IML Ready
2    start mod1(x);
2  !                /* Line 1 */
3    y=1;
3  !      /* Line 2 */
4    w=mod2(x);
4  !            /* Line 3 */
5    z=2;
6    sum = x + y + w;
7    return sum;
8    finish;
NOTE: Module MOD1 defined.
9
10   start mod2(x);
10 !                /* Line 1 */
11   a=1;
11 !      /* Line 2 */
12   b=2;
12 !      /* Line 3 */
13   c=log(x);
13 !           /* Line 4 */
14   d=4;
15   return a+b+c+d;
16   finish;
NOTE: Module MOD2 defined.
17   q1 = mod1(1);
18   q2 = mod1(-1);
ERROR: (execution) Invalid argument to function.

 operation : LOG at line 13 column 6
 operands  : x

x      1 row       1 col     (numeric)

        -1

 statement : ASSIGN at line 13 column 1
 traceback : module MOD2 at line 13 column 1
             module MOD1 at line 4 column 1

NOTE: Paused in module MOD2.

From your description, it sounds like you are loading some modules and want to find the offending line in the stored module. To do that, you MUST have access to the original source of the module so that you can count the offset lines. The START statement is Line 1 and the lines increment with each complete statement (basically, count semicolons).  For example, here is the same program, but this time we STORE and LOAD the modules. The error is in a stored module:

 

proc iml;
start mod1(x);      /* Line 1 */
  y=1;              /* Line 2 */
  w=mod2(x);        /* Line 3 */
  z=2;
  sum = x + y + w;
  return sum;
finish;

start mod2(x);      /* Line 1 */
  a=1;              /* Line 2 */
  b=2;              /* Line 3 */
  c=log(x);         /* Line 4 */
  d=4;
  return a+b+c+d;
finish;
store module=(mod1 mod2);
QUIT;

proc iml;
load module=(mod1 mod2);
q1 = mod1(1);
q2 = mod1(-1);
quit;

The log looks like this:

2988  q2 = mod1(-1);
ERROR: (execution) Invalid argument to function.

 operation : LOG at offset   4 column   8
 operands  : x

x      1 row       1 col     (numeric)

        -1

 statement : ASSIGN at offset   4 column   3
 traceback : module MOD2 at offset   4 column   3
             module MOD1 at offset   3 column   3

NOTE: Paused in module MOD2.

The top of the log tells you that the there is an invalid argument to the LOG function and that the argument is the symbol x, which has the value -1.  Many times you can find the error using that information. If not, the next section tells you more. The error is during an assignment statement (c=...) on the 4th line of the MOD2 module, where the START statement is Line 1. The 'column 3' information tells you the location of the equal sign. The error occurs when trying to form the expression to assign to C.

 

Hope this helps. 

rbettinger
Lapis Lazuli | Level 10

Very nice explanation, Rick. You have helped me to deepen my understanding of IML.

Thank you very much for a comprehensive answer,

Ross

rbettinger
Lapis Lazuli | Level 10

Your DO-Loop posting is a very clear, complete walk-through (traceback? ;-| ) of debugging an IML module.

Thanks, Rick!

hackathon24-white-horiz.png

2025 SAS Hackathon: There is still time!

Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!

Register Now

From The DO Loop
Want more? Visit our blog for more articles like these.
Discussion stats
  • 4 replies
  • 2358 views
  • 1 like
  • 2 in conversation