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