Example: Isolating a Heap Corruption Using a Macro

Provides an example program and a technique you can use to isolate a heap corruption using the PL/I macro preprocessor and a provided include file.

If you are still unable to easily spot the location that is causing the memory corruption using the suggestions provided thus far, the technique shown in the following example can be particularly helpful.

Example program, foo.pli:

/* Example PL/I Program demonstrating a memory corruption 
    and the use of a macro to run down the point of failure.
    To compile: 
      mfplx -macro -incafter checkstomp.inc foo.pli 
 */

 foo: proc() options(main);

  dcl stompee1 char(10) based(stompptr);
  dcl stompee2 char(14) based(stompptr);
  dcl stompptr ptr;

  on error 
    begin;
      call PLIDUMP('FBCAT', 'Demo Memory Corruption');
    end;

  alloc stompee1; /* 10 bytes */
  stompee1 = '0123456789';  /* assign 10 bytes - happy happy */

  /* memory should be clean */
  $CHECKSTOMP();

  /* Create memory stomp and try again */
  stompee2 = 'ABCDEFGHIJKLMN'; /* pump in 14  and corrupt guard bytes */

  /* should be stomped! */
  $CHECKSTOMP();

 end foo;

The example program intentionally creates a memory stomp of heap-based memory using $CHECKSTOMP();. When compiled using the command line cited in the comment text, it generates macro code to isolate to the statement where the corruption occurs. This includes code that drives a message to SYSPRINT and/or CTF Trace. It also drives an ERROR condition that generates a PLIDUMP showing the call stack, variable values, etc.

We recommend that you follow these steps to compile the example program and generate the macro code:

  1. Set up your environment to compile foo.pli using the checkstomp.inc include file. checkstomp.inc is provided in your %ProgramFiles(x86)%\Micro Focus\Enterprise Developer\include directory for version 9.0 and later.
    Note: checkstomp.inc is backwardly compatible with Enterprise Developer versions 6.0, 7.0, and 8.0.
  2. Compile using the following command:
    mfplx -macro -incafter checkstomp.inc -pp
    foo.pp foo.pli

    Where foo.pp is an intermediate output file containing the code generated by the macro.

We highly recommend that you review the macro-generated code until you have a solid understanding of what it does. At that point, you can apply this technique to your own PL/I program to identify the statement where the corruption occurs:

  1. Add $CHECKSTOMP(); invocations within your program code at strategic points as shown in the example.
  2. Compile your program as follows:
    mfplx -macro -incafter checkstomp.inc -pp
    prog-name.pp prog-name.pli
  3. Run the program.
  4. Review the SYSPRINT, CTF Trace, and PLIDUMP output and any other information generated by the program.

Sample session:

c:\work\emergency\jan13
ED>mfplx -macro -incafter checkstomp.inc -pp foo.pp foo.pli

c:\work\emergency\jan13
ED>foo

Memory Clean: FOO Line #(22)
Memory Corruption detected: FOO Line #(28)