Re: Pointer corruption errors...



On Tue, 9 Jan 2001, Craig Durkin wrote:

Hi there. I'm a gtk newbie, and I can't for the life of me figure out this weird error. I'm writing a 
directory recursion function to store all directories in a hierarchy in a tree, but I seem to have some 
pointer corruption problems. The function is as follows:

OK, there are several problems here.  I'll step through the function.
 
GtkWidget
*recurse_dir2(gchar *opath) {
        gchar *path = g_malloc(sizeof(char));

Firstly: you don't need to make a copy of 'opath': you can just pass that
straight into opendir(), so there should be no need to malloc here.

        GtkWidget *tree, *root = g_malloc(sizeof(GtkWidget));

GTK's gtk_x_new functions all allocate memory for you, so there is no need
to do this (and it will leak memory when you use the GTK functions).

Instead:

GtkWidget *tree, *root;

        DIR *dir = g_malloc(sizeof(DIR));

opendir() also takes care of the memory allocation...

        struct dirent *dirent;

        strcpy(path, opath);

Here, you are copying opath over the top of a single character buffer,
meaning that if opath points to a string other than just a null
('\0') character, it will overwrite memory which you didn't allocate (you
only allocated one character of memory), hence the pointer
corruption.  The preferred way to do this would be to do 

path = g_strdup(opath)

This achieves what you want - it allocates enough memory to hold the
contents of opath (plus the terminating null character) and then copies
the string into the memory.  You need to g_free() this when you have
finished with it.

        if (!(dir = opendir(path)))
                return 0;
        tree = gtk_tree_new();
        root = gtk_tree_item_new_with_label(path);
        gtk_tree_append(GTK_TREE(tree), root);
        while ((dirent = readdir(dir)) != NULL)
        {
                if (dirent->d_type == DT_DIR && *dirent->d_name != '.')

This is not very portable: to quote the Linux readdir manpage:

       According  to POSIX, the dirent structure contains a field
       char d_name[] of unspecified size, with at  most  NAME_MAX
       characters  preceding the terminating null character.  Use
       of other fields will harm the  portability  of  your  pro-
       grams.

The best way to check if it is a directory is to use the stat() system
call instead, see my example, below.  I apologise if you are doing this
deliberately (eg you want to avoid stat()).

                {
                        return 1;
                }
                dirent = (struct dirent *)((unsigned int)dirent+dirent->d_reclen);
        }

        return tree;

}

Here is a short example to illustrate how to read a directory and use
stat() to test the files:

int read_directory (char *path) {
  DIR *dir;
  struct dirent *ent;
  struct stat stbuf;

  if((dir = opendir(path)) == NULL)
    return(-1);

  while((ent = readdir(dir)) != NULL) {
    if(stat(ent->d_name, &stbuf) == -1) {
      closedir(dir);
      return(-1);
    }

    if(S_ISDIR(stbuf.st_mode) && ent->d_name[0] != '.')
      /* This entry is a directory */
      do_whatever(ent->d_name);
    else
      /* This entry is a file/device/fifo/socket etc. see stat(2)
         for more macros to test stbuf.st_mode with */
      do_something_else(ent->d_name);
  }

  closedir(dir);

  return(0);
}

Hope this helps

Jonathan









[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]