Thread: Why is this a memory leak?

  1. #1
    Registered User deadpoet's Avatar
    Join Date
    Jan 2004
    Posts
    50

    Question Why is this a memory leak?

    Hello to all, it is really great to see the message board back in action. In my book, this is one of the best websites for programming.

    With all the cusos out of the way, I have a question that has been bothering me for days. I am going to try to scale the code down so that I do not bore anyone to death while still providing a accurate picture of what is going on.


    Code:
    #include <stdlib.h>      /* Used for standard C/C++ operations.               */
    #include <limits.h>      /* Used to get the defined system limits.            */
    #include <unistd.h>      /* Used for pathconf, _PC_PATH_MAX.                  */
    #include <string.h>      /* Used for string operations like strcpy and memset */
    #include <sys/dirent.h>  /* Used for directory structures and operations.     */
    #include <sys/types.h>   /* Used for primitive system types.                  */
    #include <sys/stat.h>    /* Used for stat structures and stat operations.     */
    #include <vector>        /* Used for vector data structures.                  */
    
    /////////////////////////////////////////////////////////////////////////////////////
    // PROTOTYPES                                                                      //
    /////////////////////////////////////////////////////////////////////////////////////
    typedef int   get_pt     ( const char *, const struct stat *, int );
    static        get_pt       get_path_type;
    static  int   get_path   ( const char *, get_pt * );
    static  int   parse_path ( get_pt * );
    
    /////////////////////////////////////////////////////////////////////////////////////
    // DEFINES                                                                         //
    /////////////////////////////////////////////////////////////////////////////////////
    #define FTW_F    1  /* file other than directory */
    #define FTW_D    2  /* directory                 */
    #define FTW_DNR  3  /* directory cannot be read  */
    #define FTW_NS   4  /* file we cannot stat       */
    
    /////////////////////////////////////////////////////////////////////////////////////
    // GLOBALS                                                                         //
    /////////////////////////////////////////////////////////////////////////////////////
    const  char *TOP_DIR = "/dev";
    static char *FULLPATH;
    
    vector<char *>  vdevice;
    vector<int>     vmajor;
    vector<int>     vminor;
    
    int main ( void ) {
      ret = get_path( TOP_DIR, get_path_type );
      for ( auto unsigned int i = 0; i < vdevice.size(); i++ ) {
        printf( "%s %d %06x\n", (vdevice.at(i)).c_str(), vmajor.at(i), vminor.at(i) );
      }
    
      for ( i = vdevice.size(); i > 0; --i ) {
        printf( "DELETING [%d] [%i]\n", vdevice.size(), (i - 1) );
        delete vdevice.at( i -1 );                                // <--------------MEMORY LEAK
      }
    
    }
    
    static int get_path ( const char *ptrPathname, get_pt *gpt ){
      ////////////////////////////////////////////////////////////////////
      // Entry point into the rest of the logic.                        //
      ////////////////////////////////////////////////////////////////////
      int ret = 0;
      FULLPATH = new char [ ( pathconf( "/", _PC_PATH_MAX ) + 1 ) ];
      memset( FULLPATH, 0, sizeof( FULLPATH ) );
    
      strcpy( FULLPATH, ptrPathname );
      ret = parse_path( gpt );
    
      if ( FULLPATH ) {
        delete [] FULLPATH;
      }
      return ( ret );
    }
    
    static int parse_path ( get_pt *gpt ) {
      ////////////////////////////////////////////////////////////////////////////////////
      // Descend through the hierarchy, starting at "fullpath".  If "fullpath" is       //
      // anything other than a directory, then lstat() it, call get_path_type [gpt], and//
      // return.  For a directory, we call ourself ( parse_path ) recursively for each  //
      // name in the directory.                                                         //
      ////////////////////////////////////////////////////////////////////////////////////
      struct stat       statbuf;
      struct dirent     *ptrDir;
      DIR               *ptrD;
      int               ret;
      char              *ptr;
    
      (void)memset( &statbuf, 0, sizeof( struct stat ) );
      
      if ( lstat( FULLPATH, &statbuf ) < 0 ) {
        return( gpt( FULLPATH, &statbuf, FTW_NS ) );  /* lstat error */
      }
      if ( S_ISDIR( statbuf.st_mode ) == 0 ) {
        return( gpt( FULLPATH, &statbuf, FTW_F ) );  /* not a directory */
      }
    
      if ( ( ret = gpt( FULLPATH, &statbuf, FTW_D ) ) != 0 ) {
        return( ret );
      }
    
      ptr = FULLPATH + strlen( FULLPATH );  /* point to the end of FULLPATH */
      *ptr++ = '/';
      *ptr   = 0;
    
      if ( ( ptrD = opendir( FULLPATH ) ) == NULL ) {
        return ( gpt( FULLPATH, &statbuf, FTW_DNR ) );  /* Cannot read directory */
      }
    
      while ( ( ptrDir = readdir( ptrD ) ) != NULL ) {
        if ( strcmp( ptrDir->d_name, "." ) == 0 |
    	 strcmp( ptrDir->d_name, ".." ) == 0 |
    	 strcmp( ptrDir->d_name, "group" ) == 0 ) {
          continue;  /* ignore dot ".", dot dot ".." and group */
        }
        strcpy( ptr, ptrDir->d_name );  /* append name after slash */
    
        if ( ( ret = parse_path( gpt ) ) != 0 ) { break; }  /* recursive */
      }
    
      ptr[-1] = 0;  /* erase everything from slash onward */
      if ( closedir( ptrD ) < 0 ) {
        printf ( "ERROR: Cannot close directory %s", FULLPATH );
      }
      if ( ptrDir ) {
         delete [] ptrDir;
      }
      return ( ret );
    }
    
    static int get_path_type( const char *ptrPathname, const struct stat *ptrStat, int type ) {
    
    //////////////////////////////////////////////////////////////////////
    // If I used string and put it into the vector it does not leak.    //
    //  string s;
    //  auto unsigned int i =0;
    
       char *s = new char [ ( pathconf( "/", _PC_PATH_MAX ) +1 ) ];
       memset( s, 0, sizeof( s ) );
       strcpy( s, ptrPathname );
      
      switch (type) {
      case FTW_F:
        switch( ptrStat->st_mode & S_IFMT ) {
        case S_IFBLK:
          //for ( i =0; i < strlen( ptrPathname ); i++ ) { s += ptrPathname[i]; }
          vdevice.push_back( s );
          vmajor.push_back( (int)major(ptrStat->st_rdev) );
          vminor.push_back( (int)minor(ptrStat->st_rdev) );
          break;
        case S_IFCHR:
          //for ( i =0; i < strlen( ptrPathname ); i++ ) { s += ptrPathname[i]; }
          vdevice.push_back( s );
          vmajor.push_back( (int)major(ptrStat->st_rdev) );
          vminor.push_back( (int)minor(ptrStat->st_rdev) );
          break;
    
    //////////////////////////////////////////////////////////////////////
    //  CODE REMOVED TO PREVENT BOREDOME                //
    //////////////////////////////////////////////////////////////////////
    
      default:
        printf ( "ERROR: unknown type %d for path %s\n", type, ptrPathname );
        break;
      }
      return ( 0 );
    }
    I cannot seem to figure out why it is considered a memory leak whan I take place "ptrPathname" into "s" and then push "s" into vector "vdevice", I am then setting up a potential memory leak.

    I have tried to clean this problem up by using various syntaxes of the delete function like, delete [] vdevice.at( i ), delete vdevice.at( i ), going both forward and backwards in the vector. But I know that the answer is simple but I am stumped. The only thing that I can figure is that I must not be getting ahold of the actual pointer.



    Thanks to any and all that respond.

    DeadPoet

  2. #2
    Registered User
    Join Date
    Feb 2004
    Posts
    46
    Code:
    delete vdevice.at( i -1 );
    This is not just a memory leak. The C++ Standard defines such a call to delete as undefined. Your initial call to request dynamic memory used new[], therefore your call to release that memory should use delete[]. Here is the correct syntax.
    Code:
    delete [] vdevice.at( i -1 );

  3. #3
    Registered User deadpoet's Avatar
    Join Date
    Jan 2004
    Posts
    50

    Thumbs up

    Thanks dude, I could have sworn that I tried that one. It appears that the leak is gone.

    Thanks,

    DeadPoet.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Memory leak in this case?
    By George2 in forum C++ Programming
    Replies: 3
    Last Post: 03-22-2008, 05:05 AM
  2. memory leak in the code?
    By George2 in forum C++ Programming
    Replies: 20
    Last Post: 01-13-2008, 06:50 AM
  3. Is this code memory leak free? ---> POSIX Threads
    By avalanche333 in forum C++ Programming
    Replies: 9
    Last Post: 04-13-2007, 03:19 PM
  4. Any Memory Leak Checking Tool?
    By George2 in forum C Programming
    Replies: 4
    Last Post: 06-21-2006, 11:02 PM
  5. Manipulating the Windows Clipboard
    By Johno in forum Windows Programming
    Replies: 2
    Last Post: 10-01-2002, 09:37 AM