INF: Using _psp for Pointer Checking

ID Number: Q66127

6.00 6.00a 6.00ax 7.00

MS-DOS

Summary:

In Microsoft C versions 6.0, 6.0a, 6.0ax, and C/C++ version 7.0, in

order to implement a pointer checking routine for your MS-DOS

application, you must first determine the beginning address of your

program in memory. The PSP (program segment prefix) is set up in the

lowest segment of available memory. However, when dynamically

allocating memory using malloc(), it is possible to receive memory

located below the address marked by _psp. This can break many pointer

checking routines that aren't aware of such behavior.

More Information:

When MS-DOS loads an .EXE or .COM file, the PSP is set up in the

lowest segment of the largest contiguous block of available memory.

There may be other blocks of available memory below the location of

the PSP; these blocks of memory are usually fairly small. If MS-DOS

returns one of these segments, when pointer checking is implemented

with the /Zr option (available only with the /qc compiler option), the

segment is simply discarded and MS-DOS is called again. This process

is repeated until a segment value greater than _psp is returned.

You can implement a similar routine in any C program by making calls

to a function, as demonstrated below, rather than making calls

directly to malloc(). However, the start-up code still will make calls

to malloc() directly for environment and argument space. Thus, the

pointer segments for the environment and arguments may still be less

than _psp. Further, it should be noted that this routine does not

implement pointer checking; it only enables programmers to implement

their own pointer checking by comparing segment values against _psp.

Another method of getting only pointer segments greater than _psp is

to modify the start-up code so that the value of _psp is stored at

_aseglo. This is the actual location used to store the lower segment

limit when pointer checking is implemented. The code to check the

segment returned by MS-DOS against this location, and to call MS-DOS

again if necessary, is already implemented. If it is necessary to have

pointer segments for the environment and argument variables greater

than _psp, a similar assignment can be used to modify the start-up

code. If this assignment is done before the space for these variables

is allocated in the start-up code, they will have segment values

greater than _psp. However, you should be aware that Microsoft can

make no guarantees about the implementation of this feature in any

future releases.

If a call to malloc() requires a new segment to be allocated from the

operating system, the call to MS-DOS will be made requesting only the

amount of memory required by the malloc(). In subsequent calls,

requests are made for 8K blocks of memory until no more memory is

available from that segment. Because the blocks of memory below the

PSP are small, they may not be allocated during the first calls to

malloc(). Thus, you cannot be sure exactly when these blocks of memory

will be allocated.

Sample Code

-----------

void * _new_malloc (size_t size)

{

void * temp_ptr;

temp_ptr= malloc (size);

while ((temp_ptr != NULL) && (FP_SEG(temp_ptr) < _psp))

temp_ptr= malloc (size);

return temp_ptr;

}

Additional reference words: S_QUICKC R6013 illegal far-pointer use

6.00 6.00a 6.00ax 7.00