1

While I am freeing the memory it it causing glibc detected error. It works fine when I give .(current directory containing single file as input). However ..(parent directory) input gives this error. I have tried to use gdb with no success. Can someone please point out the problem. Thanks. Below is the code.

 /*
*********************************************************************
*File Name - function.c
Purpose    - Implementation of functions like iteration, open_read to 
      printf directories and file properties.
**********************************************************************
*/

#include "header.h"


gboolean iterator(GNode* _node, gpointer data) 
{
  guint _node_depth = g_node_depth(_node);

  printf("%p insert _ \t%p data\n",_node,_node->data);

  if( _node_depth>1 ) 
  {
    printf("%.*s",(_node_depth-2)*2,"           ");
    printf("%s\n",(char *)_node->data);
  }
  return SUCCESS;
}

gboolean destroyer(GNode* node, gpointer data)
{
  printf("\nfrom destroyer: ");
  printf("%pnode\t data %p\n",node,node->data);
  free(node->data); 
  return SUCCESS;
 }


void open_read( char* input_dir ,GNode* parent)
{
  int count = 0;
  DIR *dir;
  struct dirent  *dp;
  char *stat_path = NULL;
  struct stat file_stat; 
  char *data = NULL;
  char *formatted_data = NULL;

  if(NULL == (dir = opendir( input_dir ) ) )
  {
    printf("cannot open %s directory",input_dir);
  }
  else
  {
    /* Loop through directory entries. */
    while( (dp = readdir(dir) ) != NULL )
    {   
      if( count >= 2 ) /* omitting '.' and '..' files */
      {
        if( dp->d_type == DT_REG )
        {       
          /* Get entry's information. */    
          stat_path = ( char * )malloc( sizeof( char ) * MAX_SIZE );
          strcpy( stat_path, input_dir );
          strcat( stat_path, dp->d_name );

          if ( stat( stat_path, &file_stat) == -1 )
          {
            printf("cant read the stats of %s",dp->d_name);
          }    
          else
          {
            data=(char*)malloc(sizeof(char) * MAX_SIZE);
            strcpy(data,dp->d_name);
            strcat(data,"\n\tLinks\tUid\ti_node\tSize\tPath\n");
            formatted_data=(char*)malloc(sizeof(char) * MAX_SIZE);
            sprintf(formatted_data,"\t%d\t%d\t%d\t%d\t%s", (int)file_stat.st_nlink, (int)file_stat.st_uid, (int)file_stat.st_ino, (int)file_stat.st_size,input_dir);
            strcat(data,formatted_data);    
            //free(formatted_data);
            g_node_insert(parent,-1,g_node_new(data));
          }   
          free(stat_path); 
        }
        else if( dp->d_type == DT_DIR )
        {
          char *sub_dir = (char *)malloc(sizeof(char) * MAX_SIZE);
          strcpy( sub_dir, input_dir );
          strcat( sub_dir, dp->d_name);
          strcat( sub_dir, "/");                    
          open_read(sub_dir, g_node_insert(parent,-1,g_node_new(dp->d_name)) ); 
        }
      }
      count++;  
    }
  }
  closedir(dir);
}


/**********************************************************************

Purpose         - Simulating the LS command
Input       - directory path from the command line
Output      - Displaying the list of directories and file properties
return      - SUCCESS OR FAILURE
***********************************************************************/

 #include "header.h"
int main(int argc, char* argv[])
{

  char *user_dir = NULL;

  /*allocating memory*/
  user_dir = (char*)malloc(sizeof(char) * MAX_SIZE);

  if (NULL == user_dir)
  {
    fprintf(stderr, "cant allocate memory...");
    return FAILURE;
  }

  /*opening and reading the directory by calling open_read()*/
  if (argc < 2)
  {
    strcpy(user_dir,"./");
  }
  else
  { 
    strcpy(user_dir, argv[1]);
    strcat(user_dir, "/");  
  }

  GNode * root = g_node_new(user_dir);
  //g_node_insert(root);
  open_read(user_dir, root);
  g_node_traverse(root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,  (GNodeTraverseFunc)iterator, NULL);
  //printf("from main():%s",root->data);
  g_node_traverse(root, G_PRE_ORDER, G_TRAVERSE_ALL, -1, (GNodeTraverseFunc)destroyer, NULL);

  g_node_destroy(root);


  return SUCCESS; 
}
dragosht
  • 3,237
  • 2
  • 23
  • 32
Tejas
  • 97
  • 8
  • Welcome to Stack Overflow! [Please see this discussion on why not to cast the return value of `malloc()` and family in `C`.](http://stackoverflow.com/q/605845/2173917). – Sourav Ghosh Dec 21 '15 at 09:37
  • regarding this line: `if( count >= 2 )` nothing in the code is setting `count` to anything but the initializer of 0. The code is missing the statement(s) to check the current directory name to assure it is not `.` nor `..`. suggest replacing the `if( count >= 2 )` with the appropriate check of the directory name: `dp->d_name` by using the strcmp() function. – user3629249 Dec 24 '15 at 03:07
  • the d_type field is not supported for all filesystem types. suggest using `stat()` and looking at the `st_mode` field, using the macros like: `S_ISREG(m)` to determine if the file is a 'regular' file – user3629249 Dec 24 '15 at 03:13
  • the expression: `sizeof( char )` is defined as 1. multiplying by 1 makes no difference in the parameter sent to `malloc()` such an expression just clutters the code, making debug and maintenance that much more difficult. Suggest removing that expression. When calling `malloc()` and family of functions, always check (!=NULL) the returned value to assure the operation was successful. – user3629249 Dec 24 '15 at 03:15
  • what is in the file `header.h` and why is it being included twice in the same file? Does `header.h` have a 'include guard'? – user3629249 Dec 24 '15 at 03:21
  • each of the memory allocations gotten via `malloc()` must be passed to `free()` before destroying the nodes. The code has numerous memory leaks. Suggest using `valguard` to find/fix all those memory leaks. – user3629249 Dec 24 '15 at 03:24
  • casting the fields from the `struct sta`t to `int` is not a good idea and can/will lead to invalid values being `formatted_data[]` array. – user3629249 Dec 24 '15 at 03:42
  • this line: ` //free(formatted_data);` should not be commented out. as each pass though the loop will overlay that pointer, resulting in memory leaks. Suggest: replacing the related call to `malloc()` with `char formatted_data[ MAX_SIZE ]` – user3629249 Dec 24 '15 at 03:47

1 Answers1

1
    char *sub_dir = (char *)malloc(sizeof(char) * MAX_SIZE);
    strcpy( sub_dir, input_dir );
    strcat( sub_dir, dp->d_name);
    strcat( sub_dir, "/");                  
    open_read(sub_dir, g_node_insert(parent,-1,g_node_new(dp->d_name)) );

Okay, so what you pass to g_node_new is not what malloc returned, so you certainly can't pass that to free.

gboolean destroyer(GNode* node, gpointer data)
{
  printf("\nfrom destroyer: ");
  printf("%pnode\t data %p\n",node,node->data);
  free(node->data); 
  return SUCCESS;
}

But you do!

I believe you intended:

    open_read(sub_dir, g_node_insert(parent,-1,g_node_new(sub_dir)) );
David Schwartz
  • 179,497
  • 17
  • 214
  • 278