Tips 'N Techniques - March 1994

Check out these tips and techniques!

Programming Tips:
Tip: Find memory overwrite problems.

Because OS/2 2.x allocates memory in 4KB pages, it isn't always easy to catch memory overwrite bugs, as shown in the following example when you write past the amount of memory you requested in malloc/DosAlloc) char *szString; szString = malloc(255); memset(szString, 0xFF, 256); You just wrote to memory that you didn't allocate, but because OS/2 really gives you a 4KB page, you will not get a trap.

C Set++ does provide debug memory management routines but has the following limitations:

It only works for free, malloc, calloc, and so forth. It does not work if you need shared memory or need to use DosAlloc calls.

The built-in debug memory management routines won't notify you when the problem happens - it finds the error the next time you execute a free, malloc, calloc, and so forth (which can be much later in your code!), and doesn't tell you where the overwrite actually happened.

Technique: Create your own versions of free, malloc, calloc, and so forth that call DosAlloc. Instead of returning the real base pointer, return +(actual size returned by OS/2)-(request size). Then, the next time you write past the memory you requested, you will immediately get a trap. And, if you are running under the debugger, you'll be sitting on the line that caused the trap! No more hunting memory overwrite problems!!

Tip: Use IBM's Presentation Manager Debugger to detect who is freeing the memory in a program that does many memory allocations.

Technique: Using the IPMD debugger, set breakpoints that watch when memory changes value. Use this to determine when memory is freed. That is, when memory is freed, the byte before the memory will get set to zero. The breakpoint you set will halt the program letting you look at the stack to see exactly which procedure freed the memory.

Tip: Customize your OS/2 windowed sessions.

Technique: To create a customized window OS/2 object on your desktop that gives you a command prompt, put the following in the Settings folder:
 * Path and Filename: *
 * Parameters: /k x:\cmd\color.cmd 38 (where x is the directory in which you create the color.cmd file)
 * Working directory: Optional

Create the color.cmd as follows: mode 80, %1 set prompt=$E[1;33;44m$E[2J set prompt=$P$G cls

Clicking on this object gives you a variable-sized 38-line window.

If you want to make the window smaller or larger, type START COLOR x at a command prompt (where x is the number of lines that you want in your window). For instance, typing START COLOR 12 at a command prompt results in a window with 12 lines.

And, if you want to get really tricky, type START 'name of program' COLOR 12. This results in a window that shows the name of the program (so all of your OS/2 windows don't have the same name).

Customizing the default window might be perfect for something you're working on - like cutting and pasting from the OS/2 clipboard or for limiting the number of lines you wish to show in one window.

But what about when you want to look at very wide outputs (for instance, SQL selects). No problem - all you need to do is create a similar OS/2 full-screen object. Do this by putting the following in the Settings folder:
 * Path and Filename: *
 * Parameters: /k x:\cmd\132.cmd (where x is the directory in which you create the 132.cmd file)
 * Working directory: Optional

Create the 132.cmd file as follows: mode 132, 43 set prompt=$E[1;33;44m$E[2J set prompt=$P$G cls

Assembler Programming Tip:
A Tip for 386 Assembler Programmers: Use a -1 in EAX and stop worrying about the flags.

Technique: You could code this as MOV EAX,-1. However, this is big and slow. An even smaller, faster way is to code this as OR EAX,-1. This performs the same function, but it is smaller and faster. The -1, in the later case, is a sign extended byte.

Device Driver Tips:
Tip: For device driver development, use a machine with FAT partitions. Crashing an HPFS machine during driver development can result in files being damaged and lengthy reboots.

Tip: For debugging, instead of using an ASCII terminal, use an old PC with a communications program, like Procomm or Telix. This allows you to enable data capture and keep a record or your debugging sessions. Keep a running record of the contents of all he registers by placing a breakpoint at the desired locations. and change the kernel debugger's default command to r;g. The r causes all the registers to appear and the g continues execution.

Tip: Place your Init section at the end of your code. Return a pointer to the beginning of the Init section at the end of Init. This releases the memory occupied by the Init section. Don't try to save space or time during Init, neither one is an issue since Init is called only once during system boot, and the memory can be given back to OS/2 at the end of Init processing.