This section of the chapter will present a simple exception handler. Because exception handlers are commonly used to handle memory faults, the example will show the exception handler working with a memory fault.

Memory exceptions can occur when an application attempts to access a guard page, attempts to use memory that has been allocated but not committed (a sparse memory object), or when an application attempts to write to memory that has read-only access. Without an application-registered exception handler, some of these exceptions might cause the application to terminate. If the application registers its own exception handler, it can correct the cause of the memory fault and continue to run.

If the application's exception handler handles the exception, it returns XCPT_CONTINUE_EXECUTION. If the routine does not handle the exception, it returns XCPT_CONTINUE_SEARCH so that the exception will be passed to the next handler in the chain.

The following code fragment shows an exception handling routine set up to deal with memory errors:

    #define INCL_BASE
    #define INCL_DOSEXCEPTIONS
    #include <os2.h>

    #define HF_STDERR 2    /* Standard error handle */

    ULONG _cdecl myHandler(PEXCEPTIONREPORTRECORD pERepRec,
                           PEXCEPTIONREGISTRATIONRECORD pERegRec,
                           PCONTEXTRECORD pCtxRec,
                           PVOID p)
    {
        ULONG   ulWritten,
                ulMemSize,
                flMemAttrs;

        APIRET  ulrc;

        /* Access violation at a known location */
        if (pERepRec->ExceptionNum == XCPT_ACCESS_VIOLATION &&
            pERepRec->ExceptionAddress != (PVOID) XCPT_DATA_UNKNOWN) {

            /* Page fault */
            if ((pERepRec->ExceptionInfo[0] == XCPT_READ_ACCESS ||
                pERepRec->ExceptionInfo[0] == XCPT_WRITE_ACCESS) &&
                pERepRec->ExceptionInfo[1] != XCPT_DATA_UNKNOWN) {

                DosWrite(HF_STDERR,
                         "\r\nPage Fault\r\n",
                         15,
                         &ulWritten);


                /* Now query the memory to find out why we faulted. */
                ulMemSize = 1;

                DosQueryMem((PVOID) pERepRec->pExceptionInfo[1],
                            &ulMemSize,
                            &flMemAttrs);

                /* If the memory is free or committed,            */
                /* we have some other problem.                    */
                /* If it is not free or not committed, commit it. */
                if (!(flMemAttrs & (PAG_FREE | PAG_COMMIT))) {
                    DosWrite(HF_STDERR,
                             "\r\nAttempt to access uncommitted memory\r\n",
                             40,
                             &ulWritten);

                    ulrc = DosSetMem((PVOID) pERepRec->ExceptionInfo[1],
                                     4096,
                                     PAG_DEFAULT |
                                     PAG_COMMIT);

                    if (ulrc) {
                        DosWrite(HF_STDERR, "\r\nError committing memory\r\n",
                                 27,
                                 &ulWritten);

                        return (XCPT_CONTINUE_SEARCH);
                    }
                    else
                        return (XCPT_CONTINUE_EXECUTION);
                }
            }
        }
        return (XCPT_CONTINUE_SEARCH);
    }


[Back] [Next]