Contents

Legal Notices

Chapter 1:
  Quick Start


Chapter 2:
  Introduction and Installation


Chapter 3:
  About Memory Analysis


Chapter 4:
  Finding Memory Leaks


Chapter 5:
  Finding Memory Errors


Chapter 6:
  Startup Options


Chapter 7:
  Viewing Error Messages


Chapter 8:
  Viewing Source Code


Chapter 9:
  Tips and Techniques


Chapter 10:
  Troubleshooting


Chapter 11:
  Obtaining Support


Chapter 5:  Finding Memory Errors

The errors that are reported by ZeroFault, whether viewed through the GUI or the zf_rpt command, have a specific format to them. They are all identified by an acronym, and most of them have a memory address that is being referenced. If the memory is a block that has been allocated then the allocation traceback is included, and if the block has been freed then the free traceback is reported as well.

Types of Memory Errors

ZeroFault may report any of the following errors during program execution. The errors that begin with "Bad" indicate that the memory being referenced is not allocated to the process, while the errors that begin with "Uninitialized" indicate that the memory in question has not been initialized, and is therefore not valid for reading.

BMR: Bad Memory Read

A BMR message is shown when ZeroFault detects a program trying to read from a memory location not allocated by the program for use. Some of the causes are:

  • Reading beyond the end of a block (this is the most common cause).
  • Reading from a location within memory that was allocated and then later freed.
  • Logic errors that cause the program to reference random memory locations.

Example:

    #include <stdlib.h>

    main()
    {
        char *p = malloc(10);
        int i;

        bzero(p, 10);
        for (i = 0 ; i <= 10 ; ++i) // should be "i < 10"
            printf("p[%d] = %d\n", i, p[i]); // BMR generated here
    }

BMW: Bad Memory Write

This error is reported when a program writes to memory that is not allocated. Bad memory writes happen when a program tries to store something in a memory location that should not be altered. This is a severe error and is very likely to cause catastrophic results later in program execution.

Example:

    #include <stdlib.h>

    main()
    {
        char *src = "hello world\n";
        int len = strlen(src);
        char *dst = malloc(len);
        int i;

        for (i = 0; i <= len; ++i)
            dst[i] = src[i];  // BMW generated here
    }

This generates a BMW when it tries to copy the NUL character from src to dst, since dst should have been allocated for strlen(src) + 1 bytes.


UMR: Uninitialized Memory Read

ZeroFault generates this error message when it detects a program trying to read from a memory location that was not initialized by the system or the application.

Example:

    #include <stdlib.h>
    struct foo {
        int a;
        int b;
    };

    main()
    {
        struct foo *p = (struct foo *)malloc(sizeof(struct foo));
        printf("p->a = %d\n", p->a);  // UMR generated here
    }

USTKR: Uninitialized Stack Read

Automatic variables (also known as local or stack variables) do not have any defined initial state unless they are explicitly initialized. Reading from an automatic variable before it has been initialized causes ZeroFault to report an Uninitialized Stack Read Error.

Example:
    #include <stdio.h>

    main()
    {
        int rc;
        char buf[BUFSIZ];

        strcpy(buf, "hello world\n");
        rc == fputs(buf, stdout);          // Note the "=="
        printf("fputs returns %d\n", rc);  // USTKR generated here
    }

Note: This error is not generated in optimized code.


UFCP: Uninitialized Function Call Parameter

Similar to an Uninitialized Memory Read (UMR), an UFCP is a memory location which is passed as an argument to a function call, and has not been initialized before the call to the function is made. ZeroFault knows the semantics of all the AIX system calls and many library calls, and it validates the parameters that are passed to these functions for correct memory usage. See System Calls for more information.

Example:

    #include <stdio.h>
    #include <stdlib.h>
    #include <strings.h>

    main()
    {
        char *foo;

        foo = (char *)malloc(10);
        bzero(foo, 9);      // Should be 10
        write(1, foo, 10);  // BFCP error generated here
    }

BFCP: Bad Function Call Parameter

The BFCP message appears when ZeroFault detects that all of the memory associated with a function call argument is not allocated by the program for use. This is similar to a BMR error, but in the context of a parameter being passed to a function.

Example:

    #include <stdio.h>
    #include <stdlib.h>
    #include <strings.h>

    main()
    {
        char *foo;

        foo = (char *)malloc(10);
        bzero(foo, 10);

        write(1, foo, 20);  // BFCP error generated here
    }

BFCT: Bad Function Call Target

The target of a function call is the location where the function call will store information. If that region is not available (either in address or length) to the program this error is reported. This is similar to a BMW, but in the context of where a function call's return value is stored.

Example:

    #include <stdio.h>
    #include <stdlib.h>
    #include <strings.h>

    main()
    {
        char *foo;

        foo = (char *)malloc(10);
        read(0, foo, 20);  // BFCT error generated here
    }


The target of the function call is foo. The read will store 20 bytes of information at foo but foo is only available for 10 bytes.


BFREE: Bad Free

When a program attempts to tell the system to release a memory block referenced by an invalid pointer, ZeroFault generates a BFREE message.

Example:

    #include <stdio.h>
    #include <stdlib.h>
    #include <strings.h>

    main()
    {
        char foo[30];

        strcpy(foo, "hello world\n");
        printf("%s", foo);
        free(foo);  // BFREE error generated here
    }

DFREE: Duplicate Free

When a program attempts to free a memory block which has already been freed, ZeroFault generates a DFREE message.

Example:
    #include <stdio.h>

    main()
    {
        FILE *f = fopen("tmp","w");
        if (f) {
            fprintf(f, "hello world\n");
            fclose(f);
            free(f);  // DFREE error generated here, the FILE
                      // struct was freed by fclose()
        }
    }

BREALL: Bad Realloc

realloc is a function which changes the size of a block of memory. When a program requests a realloc for a memory block which has not been allocated to begin with, ZeroFault generates a BREALL message.

Example:
    #include <stdio.h>
    #include <stdlib.h>
    #include <strings.h>

    main()
    {
        char inbuf[BUFSIZ], outbuf[BUFSIZ];
        char *foo = outbuf;                // should be malloc()ed
        int foolen = sizeof(outbuf);

        foo[0] = '\0';
        while (fgets(inbuf, sizeof(inbuf), stdin)) {
            if (strlen(inbuf) + strlen(foo) + 1 > foolen)
                // BREALL generated on following call
                foo = realloc(foo, foolen += BUFSIZ);
            strcpy(foo + strlen(foo), inbuf);
        }
        fputs(foo, stdout);
    }

RNULL: Null Pointer Read

When a program attempts to use a pointer which references memory location zero, ZeroFault generates an RNULL message.

Example:
    #include <stdio.h>
    #include <stdlib.h>
    #include <strings.h>

    main()
    {
        char buf[BUFSIZ];
        char *p = fgets(buf, sizeof(buf), stdin);

        // if fgets() failed then the next line generates an RNULL
        printf("p[0] is %d\n",p[0]);
    }

Note: This error is not generated in optimized code.


WNULL: Null Pointer Write

When a program attempts to set a pointer to reference memory location zero, ZeroFault generates a WNULL message.

Note: A program will always get a segmentation violation immediately following a WNULL error, since the page pointed to by a NULL pointer is read-only under AIX.

    #include <stdio.h>
    #include <stdlib.h>
    #include <strings.h>

    main()
    {
        char buf[BUFSIZ];
        char *p = fgets(buf, sizeof(buf), stdin);

        // if fgets() failed then the next line generates a WNULL
        p[0] = '\0';
    }

WMSG: Warning Message

ZeroFault generates warning messages when the process attempts to do things that ZeroFault will not allow. The two conditions that currently generate a WMSG are when the process attempts to close the file descriptor used by ZeroFault to send information to or from the user interface and when the process attempts to override signal handlers installed by ZeroFault to communicate with the user interface and generate memory leak snapshots.

Some applications attempt to reset all signal handlers or close all file descriptors at startup or after a fork. These applications cause WMSG warnings to be generated, but these can generally be ignored, since there should be no impact on the program.


UNREF_BLOCK: Unreferenced Block

When you generate a memory leak report, ZeroFault displays a list of unreferenced, or leaked, blocks. When a program gets a pointer back from a malloc call, then destroys the pointer without first calling free, the block of memory once referenced by the destroyed pointer can no longer be freed or used and thus is known as an unreferenced block.


SEGV: Signal SIGSEGV Received

When the application receives the SEGV signal, ZeroFault generates this error message and terminates the process. Garbage collection is not performed.

 

© Copyright 2013 The ZeroFault Group, LLC. All rights reserved. All logos and trademarks are property of their respective owners.