Finding Run-time Memory Errors

Taed examines the problems arising from array-bounds violations--stack corruption, segmentation violations, and ultimately, programmer insanity. Although focusing on Purify 2.0, he also looks at Insight, Sentinel, MemCheck, and Bounds-Checker.


November 01, 1993
URL:http://www.drdobbs.com/architecture-and-design/finding-run-time-memory-errors/184409108

Figure 1


Copyright © 1993, Dr. Dobb's Journal

Figure 1


Copyright © 1993, Dr. Dobb's Journal

NOV93: Finding Run-time Memory Errors

Finding Run-time Memory Errors

A sophisticated tool for the thorniest of bugs

Taed Nelson

Taed is a senior software engineer at National Semiconductor Corporation. He can be reached via the Internet at [email protected].


Probably the most insidious bug-infesting C programs is the array-bounds violation. In its more subtle forms, it merely leads to slightly incorrect results. Virulent strains can cause stack corruption, segmentation violations, and ultimately, programmer insanity. A wide variety of free and commercial malloc() debugging packages are available to help combat this plague. Unfortunately, they're awkward to use and only address part of the problem.

However, a number of "modern" tools designed to detect memory-related errors are now available. These tools, such as Purify from Pure Software, Insight from Parasoft, MemCheck from StratosWare, and Sentinel from Virtual Technologies, are modern in that they perform sophisticated checking and generate detailed reports of C/C++ programs at run time. In this article, I'll focus on Purify 2.0. For information on other tools, see the accompanying textbox entitled "Run-time Debuggers."

Besides array-bounds violations, Purify 2.0 detects memory leaks and the use of uninitialized memory, NULL pointers, and free()ed memory. (Figure 1 lists errors Purify can catch.) Currently, Purify is available only on Sun SPARC-stations, but HP 9000-support is forthcoming. It supports C, C++, and Fortran 77. I've used it with cc and CC from Sun, lcc from Lucid, and GNU gcc and g++ from Free Software Foundation. Pure Software supports a number of other compilers as well.

Innocence Lost

Although I write software for different platforms, my primary project has been OPAL, a PLD programming package consisting of 20 programs and 80,000 lines of code, which supports both DOS and Sun UNIX environments. Since DOS is tolerant of memory errors, we decided to focus quality assurance on the UNIX platform, where a segmentation violation is likely.

The result was a brute-force malloc() replacement (written by Andy Valencia, of Sequent, and myself) which could detect array-bound violations of malloc()ed memory. Unfortunately, it used enormous amounts of memory (a minimum of two virtual pages--typically 8K--for each malloc() call), which usually thrashed the system, and frequently exhausted all available virtual memory. I first ran across Purify at the Winter 1992 USENIX conference. Since then, I've used Purify on every program I've written, as well as on the public-domain packages to which I contribute.

Overview

Purify can be used almost immediately after installation. To illustrate how to use it, I've written a short program (see string1.c, Listing One, page 92) which contains a number of errors. While the example is admittedly contrived, all the errors are familiar to C programmers. For the sake of illustration, imagine the code is tens of thousands of lines long where you would have only a small chance of finding the errors by sight.

Purify can be run either from the command line or from within a make file by prefixing your normal linking command with the command purify. Although I'm compiling with the -g debugging option, Purify doesn't require it. If you use -g, Purify will produce more readable error messages. Since there's only one source module, I'll skip the make file and type purify gcc -g -o string string1.c.

Purify first allows gcc to compile string.c, intercepting the link step. It then modifies the object file string.o and the standard library libc.a to insert all of its own error checking code. It then uses its own incremental linker to produce the executable file.

Unitialized Memory Read

When execution of string starts, Purify verifies you have a license. If so, it runs normally, but whenever an error is detected, it prints a message. Since the messages are sent to stderr, they are easy to separate from normal program output. The messages produced by Purify are shown in Listing Two, page 92; these are edited for brevity in subsequent runs.

The first reported error is an "unitialized memory read" of the local variable string on line 13 of string1.c, the stringCopy() function call. Returning to the source file, you'll notice I passed string as an argument without initializing it to a section of allocated memory. Knowing a bit about pointers, I suspect that the garbage pointer is what lead to the second error, a segmentation violation. Purify specified the stack frame and line number of both errors. The familiar UNIX message "segmentation fault" doesn't convey this information.

The first error is easy enough to fix; the modified version of main() is in Listing Three, page 92. Compiling is much faster this time since the Purify-ed version of libc.a had been cached. Nevertheless, when I run my program (Listing four, page 92), I still have an unitialized memory read, but it's due to the local variable length in stringCopy(). Purify shows the entire stack frame and size of the error. Also, since the program didn't crash this time, a summary is printed at the end.

Once again, the error is simple to fix by initializing length to 0. After I compile and run this version, Purify reports no errors. Feeling overjoyed, I decide to exercise my program a bit with different strings. The new program is in Listing Five, page 92.

Array Bounds Violations and NULL Pointers

When I first run the new version, it produces a long list of errors. To shorten this list, I use Purify's batch mode by entering purify -batch gcc -g -o string string3.c. This option consolidates all error messages of the same type that occur on the same line. This output is shown in Listing Six, page 92. This report shows I had an "array bounds write" error by writing past the end of my malloc()ed memory. The report identifies where the error occurs, where that memory was allocated from, and the amount of memory allocated.

When I examine my code, I realize I neglected to allocate enough memory to store each of my strings, specifically the second. I can either fix this by allocating more memory, or by passing an additional parameter to stringCopy(). Since the latter is more general, I go with that alternative. (Lack of array size testing is one of the programming mistakes that the Internet Worm used to its advantage.)

The report also identifies the obvious use of the NULL pointer. At first, you may not think that this feature is special; after all, UNIX "reports" the error with a segmentation violation. The advantage is that Purify identifies the line number and stack frame when the error occurred. This is a trivial error to fix by checking that neither "source" nor "destination" are NULL. In addition to the two bug fixes, I decide to get a bit fancy with my testing by adding a loop; see Listing Seven page 92.

Memory Leaks

In the newest version (see Listing Eight, page 92) all of my access errors have been fixed. The report now identifies 300 bytes of leaked memory. A memory leak is allocated memory that has no active pointer pointing to it. Purify also identifies potential memory leaks, those areas that have a valid pointer that isn't pointing at the first byte. Usually, potential leaks are due to incrementing a pointer across a string and not freeing it. However, they sometimes hint at a variety of other problems.

Many C programmers have been conditioned not to worry about memory leaks since the memory is reclaimed by the operating system when the program ceases execution. However, neglecting to free() memory used early in a program's execution can cause large programs to page fault unnecessarily or run out of virtual memory. The X Window System and programs built on top of it are notorious for this type of error, particularly since some of us remain logged in for months at a time.

In this case, since Purify points out exactly where the memory was allocated, I realized that I forgot to free() my allocated memory. This memory leak is easy to fix by placing free(string); at the end of the loop. After this change, the program runs as expected and Purify reports no errors with it.

Purify's API

Purify provides a large number of functions which can be called from a debugger (such as dbx or gdb), or from within the program itself. Functions are provided to control the batch mode, print to the log file, report on the state of memory leaks, and to print detailed information about memory locations. Many of these are useful within an assert() statement to ensure that previously fixed problems do not return.

In addition, watchpoints are provided to break on read, write, allocation, free, entry, or exit of a specific or range memory location. From within a debugger, it's also possible to break on any detected error.

Error Suppression

Purify will sometimes detect a violation that you know is acceptable. Usually it is a known error that does no harm, in a library over which you have no control, or one that hasn't been fixed yet. Occasionally, it will be due to a bit of strange code that confuses Purify.

Purify messages can be suppressed by using a .purify file. This file can exist in your home directory (for general problems), or in the current directory (for project-specific problems). I have in my home directory a .purify file which contains the entry "suppress abw tzload," where abw stands for "array bounds write." This fixes a bug that SunOS 4.1.1 has in its standard version of tzload(), a routine called by many of the time functions, which writes one byte past the end of allocated memory. A relative of the offending code is in Listing Nine, page 92. I am supplying this code not to point fingers at Sun, but to show that these types of errors can crop up in extremely reliable commercial code.

It's also possible to suppress errors based on a certain stack frame. For example, instead of ignoring all "array bounds writes" in tzload(), I may only wish to suppress them if tzload() is called from tzsetwall(). To do this, my .purify file would contain suppress abw tzload tzsetwall. The use of wildcards is allowed.

Purify's Innards

The first phase of Purify runs after compilation and before linking. It takes each object file and library and inserts a special function call before every memory access. It inserts additional code during stack frame creation, and within malloc() and free(). Since it is the object files that are modified, Purify can detect errors in all aspects of the program, even hand-optimized assembly code and commercial libraries for which no source is available.

The second phase starts during run time, when the additional code is executed. This code overhead maintains and checks a two bit entry for every byte in the heap, stack, data, and bss sections. The entry indicates the state of the byte: unallocated, allocated but uninitialized, or allocated and initialized. By checking this state on every access, Purify can easily detect the use of stray pointers (unallocated memory), memory that has been free()ed, and uninitialized memory.

However, since Purify operates at the instruction level, it cannot detect stray instruction fetches; that is, a runaway program counter, like those products that utilize debugging modes within the microprocessor itself. On the other hand, this type of error is rare, and will quickly be rewarded with a segmentation violation on UNIX. It is also likely that Purify would detect the cause of the invalid program counter, which is often caused by corrupting the stack with an out-of-bounds write to a local array.

Unfortunately, Purify will also overlook unitialized bits within a byte, as long as at least one bit has been initialized. This can result from the use of an operator assignment expression, see Listing Ten, page 92. Purify Software did this intentionally for subtle reasons.

Array bounds violations are detected in a similar manner by allocating extra space both before and after the requested memory and marking that space as unallocated. This is done for both malloc()ed and static arrays. An extremely bad array-bounds violation; for example, array[1000] on a 10-byte array, has some small chance of ending up in the valid section of another array, but I've never seen this happen in practice.

Performance Issues

It's no surprise that Purify affects program performance. Although, based on the poor performance of my previous home-grown tools and Purify's many additional features, I'm satisfied with the cost.

Link-time performance can be poor. The first link of a program will take about ten times longer than usual. After that, though, it will only take a few times as long because Purify caches the modified object files, and uses an incremental linker by default. Although these cached files tend to clutter your project directory, the documentation does show exactly how to set up a crontab entry to remove old ones.

Run-time memory use is about 50 percent more than usual. About half of this increase is due to the two-bit state of each byte, and the remainder is due to the larger executable file. The executable file is typically about three times larger than normal, due to the inserted Purify code. With large applications, the extra memory usage becomes a concern due to the performance degradation caused by page swapping.

Run-time speed is generally three times slower, plus a few seconds overhead for license detection. For the types of programs I typically write this isn't a hindrance, so I use Purify all the time. Purify-ed programs which make use of a GUI, particularly those built on top of X Window, could quickly annoy the user. This is especially true if the machine has little real memory (less than 16 Mbytes). Programs that perform a lot of memory allocation and freeing also experience slow-downs since the memory is not reallocated immediately.

For More Information

Purify 2.0

Pure Software Inc.

1309 South Mary Avenue

Sunnyvale, CA 94087

408-720-1600

[email protected]

Run-time Debuggers

Purify is just one run-time debugging tool available for programmers. Other UNIX-based tools include Sentinel from Virtual Technologies (Dulles, VA) and Insight from Parasoft (Pasadena, CA). For PC developers, there's MemCheck from StratosWare (Ann Arbor, MI) and Bounds-Checker from Nu-Mega (Nashua, NH). All of these tools are roughly equivalent in functionality, yet the cost varies from $99.00 for MemCheck to $1298.00 for Purify. They all detect memory leaks, bad pointers, malloc() and free() mismatches, and boundary violations of malloc()ed memory. Most also catch memory leaks, reading unitialized memory and bad C library function calls.

Purify is the only tool that works at the object-code level, which, in theory, enables it to work with any language, compiler, or library. Unfortunately, this makes it very system-dependent, and it's only available on the Sun SPARC-station and HP 9000.

Sentinel, available on most UNIX platforms, is similar in functionality to Purify, but operates as a wrapper around the standard C library. Thus, it only detects memory errors passed as arguments to one of the library functions. This restricts its use on specialized programs and code in languages other than C/C++.

Insight is also available for most UNIX workstations. It operates at the C source-code level by inserting function calls around each line of code. In some cases, this enables it to detect errors better than the other products. However, it can't be used on libraries for which source isn't available, or on code which isn't written in C. It also provides a graphical debugging tool for examining run-time memory use, and some compile-time errors which I had only previously seen in GNU gcc (such as printf() type-checking).

On the PC side, MemCheck, available for DOS, Windows, and Macintosh, operates similar to Sentinel by checking all calls to the standard C Library. It also shares the same problems.

Bounds-Checker, available for DOS and Windows, is an automatic tools that pops up when it detects problems in the heap, stack, or data segment, and finds illegal memory accesses. The DOS version is not as powerful as the other products, delivering only a better version of UNIX's "segmentation violation." (For details on the Windows version, see "Debugging Windows Applications," page 78.)

To give you a flavor of each, these tools were used on the program in Figure 2. Listings Eleven through Fifteen, page 93, show the output. Listing Eleven is the Purify report, Listing Twelve, the Sentinel, and Listing Thirteen is that of Insight. Listing Fourteen is the report generated by MemCheck and Listing Fifteen that from Bounds-Checker.

All of the tools detected both errors in that simple example. While Purify, Sentinel, and Insight each give a great deal of information, there's something to be said for MemCheck's brevity and Bounds-Checker's pop-up environment.

--T.N.

Figure 1: The errors caught by Purify

Figure 2: Test.c, a sample program with two errors.

1   #include <string.h>
2   #include <malloc.h>
3
4   const char *Hello = "Hello, world!";
5
6   int main (int argc, char *argv[])
7   {
8      char *string;
9
10  /* Allocate memory, but we forgot the null character. */
11  string = (char *) malloc (strlen (Hello));
12
13  /* Copy, but it will copy the last byte into unallocated memory. */
14  strcpy (string, Hello);
15
16  /* Leave, but we didn't free() string. */
17  return (0);
18  }



_FINDING RUN-TIME MEMORY ERRORS_
by Taed Nelson


[LISTING ONE]

/* Copy the entire string from source to destination.   */
/* Return the number of characters copied.      */
unsigned int stringCopy (char *destination, const char *source)
{
    unsigned int length;
    while ((*(destination++) = *(source++)) != '\0') {
        length++;
    }
    return (length);
}
int main ()
{
    char *string;
    stringCopy (string, "Hello world!");
    exit (0);
}


[LISTING TWO]



Purify'd string  (pid 12837)
 Purify 2 (C) 1990-93 Pure Software Inc.  Patents Pending.
 Contact us at:  [email protected] or (408) 720 1600.
 In Europe:  [email protected] or (+44) 61 776 4499.
 Purify checking enabled.

****  Purify'd string  (pid 12837)  ****
Purify (umr): uninitialized memory read:
  * This is occurring while in:
    main         [line 19, ~nelson/Papers/string1.c, pc=0x19ad4]
    start        [crt0.o, pc=0x2064]
  * Reading 4 bytes from 0xf7fff8a4 on the stack
    This is local variable "string" in function main.

****  Purify'd string  (pid 12837)  ****
Purify (cor): Received signal 11
SIGSEGV (segmentation violation, signal bit = 0x00000400), may dump core:
  * This is occurring while in:
    etext        [/n/share/src/gnu/gcc/gcc-2.3.2/libgcc2.c, pc=0x85720]
    main         [line 19, ~nelson/Papers/string1.c, pc=0x19ae8]
    start        [crt0.o, pc=0x2064]
  * Handler function: SIG_DFL
  * Current signals: 0x00000400 (SIGSEGV)
  * Pending signals: 0x00000000


[LISTING THREE]


int main (void)
{
    char *string;
    string = (char *) malloc (20);
    stringCopy (string, "Hello world!");
    exit (0);
}



[LISTING FOUR]



Purify (umr): uninitialized memory read:
  * This is occurring while in:
    stringCopy   [line 8, ~nelson/Papers/string2.c, pc=0x21744]
    main         [line 21, ~nelson/Papers/string2.c, pc=0x217dc]
    start        [crt0.o, pc=0x2064]
  * Reading 4 bytes from 0xf7fff814 on the stack
    This is local variable "length" in function stringCopy.

****  Purify'd string  (pid 12878)  ****
  * 1 access error.
  * Basic memory usage:
      262136 code
      273000 data/bss
       16392 heap
        1864 stack
  * Shared library memory usage:
      696320 libc_pure_200.so.1.8   (shared code)
       16384 libc_pure_200.so.1.8   (private data)
        8192 libinternal_stubs.so.1.0   (shared code)
        8192 libinternal_stubs.so.1.0   (private data)


[LISTING FIVE]


#include <stdio.h>
/* Copy the entire string from source to destination.   */
/* Return the number of characters copied.      */
unsigned int stringCopy (char *destination, const char *source)
{
    unsigned int length = 0;
    while ((*(destination++) = *(source++)) != '\0') {
        length++;
    }
    return (length);
}
int main (void)
{
    char *string;
    string = (char *) malloc (20);
    stringCopy (string, "Hello world!");
    stringCopy (string, "supercalifragilisticexpialidocious");
    stringCopy (string, "");
    stringCopy (NULL, NULL);
    exit (0);
}


[LISTING SIX]


****  Purify'd string  (pid 13077)  ****
Purify (abw): array bounds write (15 times):
  * This is occurring while in:
    stringCopy   [line 9, ~nelson/Papers/string3.c, pc=0x21730]
    main         [line 24, ~nelson/Papers/string3.c, pc=0x21824]
    start        [crt0.o, pc=0x2064]
  ==== At first occurrence: ====
  * Writing 1 byte to 0x85774 in the heap
    1 byte past end of a malloc'd block at 0x85760 of 20 bytes
  * This block was allocated by malloc called from:
    main         [line 21, ~nelson/Papers/string3.c, pc=0x217e8]
    start        [crt0.o, pc=0x2064]

****  Purify'd string  (pid 13077)  ****
Purify (npr): null pointer read: reading 1 byte from 0x0
  * This is occurring while in:
    stringCopy   [line 9, ~nelson/Papers/string3.c, pc=0x21724]
    main         [line 26, ~nelson/Papers/string3.c, pc=0x21850]
    start        [crt0.o, pc=0x2064]

****  Purify'd string  (pid 13077)  ****
Purify (cor): Received signal 11
SIGSEGV (segmentation violation, signal bit = 0x00000400), may dump core:
  * This is occurring while in:

   etext        [~nelson/Papers/string3.c, pc=0x85778]
    main         [line 26, ~nelson/Papers/string3.c, pc=0x21850]
    start        [crt0.o, pc=0x2064]



[LISTING SEVEN]


#include <stdio.h>

#define MAX_STRING 100
const char *StringList[] = {
    "Hello world!",
    "supercalifragilisticexpialidocious",
    "",
    NULL
};
/* Copy the entire string from source to destination.   */
/* Return the number of characters copied.      */
unsigned int stringCopy (char *destination, const char *source, unsigned int size)
{
    unsigned int length = 0;
    if ((source == NULL) || (destination == NULL)) {
        return (0);
    }
    while ((length < size) &&
           ((*(destination++) = *(source++)) != '\0')) {
        length++;
    }
    return (length);
}
int main (void)
{
    const char **example;
    char *string;
    /* Test all of the example strings in StringList. */
    for (example = StringList; *example != NULL; example++) {
        string = (char *) malloc (MAX_STRING);
        stringCopy (string, *example, MAX_STRING);
        printf ("The copied string is \"%s\".\n", string);
    }
    exit (0);
}


[LISTING EIGHT]



Purify: Searching for all memory leaks...
There are 200 leaked bytes (44.6% of the 448 allocated bytes in the heap)

      100 bytes (2 times).     Last memory leak at 0x858d0
Report (mlk): 200 total bytes lost, malloc called from:
    main         [line 38, ~nelson/Papers/string4.c, pc=0x218a0]
    start        [crt0.o, pc=0x2064]

 Purify Heap Analysis (combining suppressed and unsuppressed chunks)

                         Chunks      Bytes
              Leaked          2        200
  Potentially Leaked          0          0
              In-Use          3        248
  ----------------------------------------
     Total Allocated          5        448



[LISTING NINE]


void tzload (void)
{
    ...
    sp->chars = (char *) calloc ((unsigned) sp->charcnt,
    ...
    for (i = 0; i < sp->charcnt; i++)
        sp->chars[i] = *p++;
    sp->chars[i] = '\0';
    ...
}



[LISTING TEN]



int main ()
{
    unsigned int data;
    data |= 0x01;
    printf ("%u\n", data);
    exit (0);
}



[LISTING ELEVEN]


Purify'd test  (pid 11557 at Sat Aug 14 09:53:44 1993)
Purify 2.1.0 SunOS 4.1, Copyright 1992, 1993 Pure Software Inc.
For contact information type: "purify -help"
Purify licensed to Pure Software Central

****  Purify'd test  (pid 11557)  ****

Purify (abw): array bounds write:
  * This is occurring while in:
        strcpy       [p9.o, pc=0xcf0c]
        main         [line 14, test.c, pc=0x1b394]
        start        [interface.c, pc=0x2064]
  * Writing 14 bytes to 0xc2ff0 in the heap (1 byte at 0xc2ffd illegal).
  * This is at the beginning of a malloc'd block of 13 bytes.
  * This block was allocated from:
        malloc       [p6.o, pc=0x46d4]
        main         [line 11, test.c, pc=0x1b36c]
        start        [interface.c, pc=0x2064]

****  Purify'd test  (pid 11557)  ****
Purify: Searching for all memory leaks...

There are 13 leaked bytes (100% of the 13 allocated bytes in the heap)

Purify (mlk): 13 bytes at 0xc2ff0 lost, allocated from:
        malloc       [p6.o, pc=0x46d4]
        main         [line 11, test.c, pc=0x1b36c]
        start        [interface.c, pc=0x2064]

Purify Heap Analysis (combining suppressed and unsuppressed chunks)
                         Chunks      Bytes
              Leaked          1         13
  Potentially Leaked          0          0
              In-Use          0          0
  ----------------------------------------
     Total Allocated          1         13

****  Purify'd test  (pid 11557)  ****
  * Program exited with status code 1.
  * 1 access error.
  * Basic memory usage:
      311288 code
      475976 data/bss
       16392 heap
        2888 stack
  * Shared library memory usage:
      696320 libc_pure_210.so.1.8       (shared code)
       16384 libc_pure_210.so.1.8       (private data)
        8192 libinternal_stubs.so.1.0   (shared code)
        8192 libinternal_stubs.so.1.0   (private data)

[LISTING TWELVE]


The SENTINEL Debugging Environment, Version 1.4.0.10
(c) Copyright 1992,1993 Virtual Technologies, Inc.

Error Output from: /t/cpcahil/./test
Running on:        rama


SENTINEL: Warning [14]: An attempt was made to access data beyond the end of an
          allocated data section.  The program attempted to write 14 bytes
          to location 0x896A8.  That address is at offset 0 in the 13
          byte data area that starts at location 0x896A8 (there is only
          room to write 13 bytes).
          Reading symbol table...Sun format...................Done

          This problem was detected at the following location:
                  strcpy()        [string.c:744]
                  main()          [test.c:14]

          This problem is *probably* associated with a 13 byte data area
          allocated on the 5th call to malloc() which returned 0x896A8.
          The context of the call to malloc() was as follows:
                  malloc()        [allocext.c:150]
                  main()          [test.c:11]

*********************** SENTINEL: LIST OF MEMORY LEAKS **********************

POINTER  STAT             LOCATION                 ALLOC       NUMBER TOTAL DATA
TO DATA                WHERE ALLOCATED             FUNCT       LEAKS    LEAKED
-------- ---- --------------------------------- -------------- ------ ----------
0x0896A8 **** main()          [test.c:11]       malloc(5)           1         13


[LISTING THIRTEEN]


**WRITE_OVERFLOW** [orig.c:15]
>>         strcpy (string, Hello);
  Writing overflows memory: string

          bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
          |                13                | 1 |
          wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

   Writing  (w) : 0x0002eca0 thru 0x0002ecad (14 bytes)
   To block (b) : 0x0002eca0 thru 0x0002ecac (13 bytes, 3 elements)
                  string, allocated at orig.c, 12

                            main()  orig.c, 15

**Memory corrupted.  Program may crash!!**

************************* INSIGHT SUMMARY *********************************
*   Program      : orig                                                   *
*   Arguments    :                                                        *
*   Directory    : /home/elephant2/whicken/D                              *
*   Compiled on  : Aug 13, 1993  13:01:32                                 *
*   Run on       : Aug 13, 1993  13:02:20                                 *
*   Elapsed time : 00:00:00                                               *
***************************************************************************

PROBLEM SUMMARY - by type
===============
          Problem                Detected      Suppressed
          -------------------------------------------------
          WRITE_OVERFLOW               1                0
          -------------------------------------------------
          TOTAL                        1                0
          -------------------------------------------------

PROBLEM SUMMARY - by location
===============
WRITE_OVERFLOW: Writing overflows memory, 1 occurrence
         1 at orig.c, 15

MEMORY LEAK SUMMARY
===================
1 outstanding memory reference for 13 bytes.

Outstanding allocated memory
----------------------------
        13 bytes      1 chunk  allocated at orig.c, 12



[LISTING FOURTEEN]


MemCheck V3.0 Active (License: StratosWare Corporation)
Strcpy at ddjtest.c(16),len=14: overwrites destination...
  destination is _fmalloc at ddjtest.c(13), size=13, #1
mc_endcheck after ddjtest.c(16): buffer overwritten before call...
  buffer is _fmalloc at ddjtest.c(13), size=13, #1
mc_endcheck: no free for _fmalloc at ddjtest.c(13), size=13, #1


[LISTING FIFTEEN]


---------------------------------------------------------------------------
F:\DDJ\WINTEST.EXE loaded 02:45 PM  Thursday August 19

---------- 03:05 PM  Thursday August 19 ----------
***** Error, Source will overrun destination ****

  Procedure:  WINMAIN  (00038H)
     Module: WINTEST
Source File:  WINTEST.C
Line Number:  00018

Trying to copy 00014  bytes to an area allocated by: WINTEST.C   LINE #
00015 starting offset within buffer 00000 The destination buffer is only
00013  bytes long.

CALL STACK
----------
#WINTEST!WINMAIN(hInstance,PrevInstance,lpszCmdLine,nCmdShow)
                (1AAE,0000,1A87:0080,0001)

***************************************************************************
                        YOUR PROGRAM'S data usage
***************************************************************************
  Stack Usage:
      stack space available           stack space used
      ---------------------           ----------------
      04908                           01018
WINTEST
  Memory used (in bytes):
      Local Heap                      Global Heap
      ----------                      -----------
      00525                           00000
  Local leaks:
      Function Name                   Size       Program location
      -------------                   ----       ----------------
      _malloc                         00013      WINTEST.C  LINE # 00015

***************************************************************************
                 GDI data usage on your program's behalf
***************************************************************************
  Memory used (in bytes):
      Local Heap                      Global Heap
      ----------                      -----------
      00000                           00000

***************************************************************************
                USER data usage on your program's behalf
***************************************************************************
  Memory used (in bytes):
      Local Heap                      Global Heap
      ----------                      -----------
      00000                           00480




Copyright © 1993, Dr. Dobb's Journal

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.