Common C/C++ Memory Errors:

Three main categories:

  1. leakage

  2. corruption: use uninitialized or unallocated memory

  3. illegal access

specific memory errors:

  1. allocate without freeing
    1. {
          char *leakage1;
          leakage1 = (char *) malloc(5*sizeof(char));
      }
      
    2.     char *leakage2;
          leakage2 = (char *) malloc(5*sizeof(char));
          ...
          leakage2 = "hello";
      

  2. uninitialized memory
        char *msg;
        printf("%s\n", msg);
    

  3. unallocated memory
        char *buffer;
        strcpy(buffer, "some data");
        scanf("%s",buffer);
    

  4. overrun the buffer
    1.     char *buf;
          buf = (char *) malloc(5*sizeof(char));
          strcpy(buf,"abcde");
      
    2.     int data[1000], i;
          for (i=0; i<=1000; i++)
              data[i] = i;
      

  5. underrun the buffer
    1.     char *buf;
          buf = (char *) malloc(5*sizeof(char));
          ...
          *(buf - 2) = '\0';
      
    2.     char buf[5];
          ...
          *(buf - 2) = 'a'
      
    3.     char c;
          short int x;
          scanf("%d%d", &x, &c);
      

  6. free buffer twice
        char *buf;
        buf = (char *) malloc(5*sizeof(char));
        free(buf);
        ...
        free(buf);
    

  7. illegal free
        char *buf, *ptr, array[100];
        buf = (char *) malloc(5*sizeof(char));
        ptr = buf + 1;
        free(ptr);
        ...
        ptr = array;
        free(ptr);
        ...
        ptr = 0;
        free(ptr);
    

  8. string operations without terminating '\0'
        char buf1[5], buf2[5];
        buf1[0] = 'a';
        buf1[1] = 'b';
        strcpy(buf2, buf1);
        ...
        printf("%s\n",buf1);
    

  9. access freed memory
    1.     char *buf;
          buf = (char *) malloc(5*sizeof(char));
          ...
          free(buf);
          strcpy(buf, "memory bomb");
      
    2.     char *fun()
          {
              char *ptr, buf[10];
              ...
              ptr = buf;
              return ptr;
          }
          
          char *dataPtr, buf[20];
          dataPtr = func();
          strcpy(buf, dataPtr);
          ...
          strcpy(dataPtr, buf);
      
    Note: therefore, it is a common practice to throw away any freed pointer values by the following
        ...
        free(ptr);
        ptr = 0;
        ...
    

  10. pointer arithmetic error
        int (*ptr)[10], buf[20][10];
        
        ptr = buf;
        *(int *)(ptr + 200*4) = 20;
        // should be ptr[19][9] = 20;
        //        or *((int *)(ptr + 19) + 9) = 20;
        //        or *((int *)ptr + 199) = 20;
    

  11. stack overrun
    1. deep recursive function call
          void bizarrePrint(int n, int buf[])
          {
              int localBuf[1000];
              int i, pivot;
              
              if (n == 1)
              {
                  printDigit(n, buf);
                  return;
              }
              else
              {
                  for (i=0; i<5; i++)
                  {
                      pivot = n*i/5;
                      copyDigit(localbuf, n/5, &buf[pivot]);
                      bizarrePrint(n-1, localbuf);
                  }
              }
          }
      
          int i;
          int buf[2000];
          for (i=0; i<2000; i++)
              buf[i] = i;
          bizarrePrint(2000,buf);
      
    2. large auto memory blocks
          void func()
          {
              double image[2000][2000];
              ...
          }
      

  12. unchecked memory allocation (illegal access)
        int i, *ptr;
        int n = 25000;
        ptr = (int *) malloc(n*sizeof(int));
        for (i=0; i<n; i++)
            ptr[i] = i;
    

  13. delete an object through second based class pointer
    class Parent1
    {
        int x;
    };
    
    class Parent2
    {
        int x;
    };
    
    class Child : public Parent1, public Parent2
    {
        int x;
    };
    
    void main()
    {
        Child  *objPtr = new Child;
        Parent1 *ptr1 = objPtr;
        ...
        Parent2 *ptr2 = objPtr;
        delete ptr2; // run time error
    }
    

  14. unmatched new/delete and new[]/delete[]
    int *ptr1 = new int;
    delete[] ptr1;
    
    int *ptr2 = new int[100];
    delete ptr2;
    

  15. null pointer error

  16. wild pointer

  17. illegal memory access

detecting memory errors:

  1. enable stack overflow check

    1. cl /Ge to enable stack overflow check for Visual C/C++
      cl /Gs to disable

    2. use preprocessor directive (VC only)
      #pragma check_stack(on)
      #pragma check_stack(off)

    3. cl /F<num> to set stack size for Visual C/C++

  2. MFC DLL

    1. Project/Settings General: using MFC as Shared DLL

    2. Before all programs: #include <afx.h>

    3. your unfreed memory (newed without delete) will be catched while running your program in debug mode (Build/Debug/Go) Note: if you use malloc/free to allocate memory, you should use new/delete at least once (ex. int *dummy=new int; delete dummy;)

  3. Electric Fence

  4. wpr

  5. stack guard

  6. version of gcc

  7. object counts

C++ 程式設計課程 首頁

製作日期: 4/02/2002 by 丁培毅 (Pei-yih Ting)
E-mail: [email protected] TEL: 02 24622192x6615
海洋大學 理工學院 資訊科學系