Identifying Memory Corruption in C and C++

May 24, 2012

Posted by Parasoft

C and C++ developers face a unique problem: many errors in their code don't manifest themselves during normal testing. Software with subtle problems such as memory corruption may run flawlessly on one machine, but crash on another.

Memory corruption is one of the most unpleasant errors that can occur with C  and C++ development, especially if it is well disguised. As an example of what can happen, consider the program shown below. This program concatenates the arguments given on the command line and prints the resulting string:

/*
 * File: hello.cMemory Error Detection
 */
#include <string.h>
main(argc, argv)
    int argc;
    char *argv[];
{
    int i;
    char str[16];
    str[0] = '\0';
    for(i=0; i<argc; i++) {
        strcat(str, argv[i]);
        if(i < (argc-1)) strcat(str, " ");
    }
    printf("You entered: %s\n", str);
    return (0);
}

If you compile and run this program with your normal compiler, you’ll probably see nothing interesting. For example:

 
c:\source> cl /Zi hello.c 
    c:\source> hello  
    You entered: hello
    c:\source>hello world
    You entered: hello world
    c:\source>hello cruel world
    You entered: hello cruel world

 

If this were the extent of your test procedures, you would probably conclude that this program works correctly, despite the fact that it has a very serious memory corruption bug.

If you compile with a memory error detection tool, the command hello cruel world generates the errors shown below, because the string that is being concatenated becomes longer than the 16 characters allocated in the declaration at line 7:

 
[hello.c:15] **WRITE_OVERFLOW**
>>         strcat(str, argv[i]);
  Writing overflows memory: <argument 1>
          bbbbbbbbbbbbbbbbbbbbbbbbbb
          |           16           | 2 |
          wwwwwwwwwwwwwwwwwwwwwwwwwwwwww
   Writing  (w) : 0xbfffeed0 thru 0xbfffeee1 (18 bytes)
   To block (b) : 0xbfffeed0 thru 0xbfffeedf (16 bytes)
                 str, declared at hello.c, 11
  Stack trace where the error occurred:
                          strcat()  (interface)
                            main()  hello.c, 15
**Memory corrupted.  Program may crash!!**
[hello.c:18] **READ_OVERFLOW**
>>     printf("You entered: %s\n", str);
  String is not null terminated within range: str
  Reading   : 0xbfffeed0
  From block: 0xbfffeed0 thru 0xbfffeedf (16 bytes)
             str, declared at hello.c, 11
  Stack trace where the error occurred:
                            main()  hello.c, 18
You entered: hello cruel world

Runtime memory error detection tools such as Parasoft Insure++ can find all problems related to overwriting memory or reading past the legal bounds of an object, regardless of whether it is allocated statically (that is, a global variable), locally on the stack, dynamically (with malloc or new), or even as a shared memory block. They also detect situations where a pointer crosses from one block of memory into another and starts to overwrite memory there, even if the memory blocks are adjacent. 

***

Photo Credit: Kevin Dooley

You can learn more about  runtime error detection and memory corruption at Parasoft's Memory Error Detection Resource Center.

New Call-to-action