Valgrind: Invalid read/write of size 8
I'm a newbie C student trying to write a directory tree. It's working no problem, but Valgrind doesn't approve. I've read posts on similar problems, but can't seem to figure it out.

I would greatly appriciate answers with not only a snippet to make it work, but also an explanation what I'm doing wrong so I won't have the same problem in the future. Feedback on why the code is bad in general won't be overlooked either :)

These are the errors from Valgrind (multiplied by amount of items handled):

	==10463== Invalid write of size 8
	==10463==    at 0x400C5D: checkDir (dirtree.c:96)
	==10463==    by 0x400F53: main (dirtree.c:135)
	==10463==  Address 0x51f88d8 is 0 bytes after a block of size 8 alloc'd
	==10463==    at 0x4C28F9F: malloc (vg_replace_malloc.c:236)
	==10463==    by 0x400BED: checkDir (dirtree.c:93)
	==10463==    by 0x400F53: main (dirtree.c:135)

	==10463== Invalid read of size 8
	==10463==    at 0x4ECFF28: __tz_convert (tzset.c:627)
	==10463==    by 0x4ECD728: ctime (ctime.c:32)
	==10463==    by 0x401022: main (dirtree.c:147)
	==10463==  Address 0x51f88d8 is 0 bytes after a block of size 8 alloc'd
	==10463==    at 0x4C28F9F: malloc (vg_replace_malloc.c:236)
	==10463==    by 0x400BED: checkDir (dirtree.c:93)
	==10463==    by 0x400F53: main (dirtree.c:135)

And her's the code (stripped of stack code):

    #include <stdio.h>
	#include <stdlib.h>
	#include <string.h>
	#include <time.h>

	#include <sys/types.h>
	#include <sys/stat.h>
	#include <unistd.h>
	#include <dirent.h>

	#define MAX_PATH_LENGTH 500
	#define MAX_ITEM_LENGTH 5000
	#define MAX_ITEM_CNT 1000

	typedef struct dirent dirent;
	typedef struct file_s {
	  char *name;
	  time_t mtime;
	} file_n;
	typedef struct itemss {
	  int filecnt;
	  file_n *files[sizeof(char*)*MAX_ITEM_CNT];
	  int dircnt;
	  char *dirs[sizeof(char*)*MAX_ITEM_CNT];              
	} items;
	typedef stack_node_s* stack_s;

	void stack_init(stack_s *stack){
		*stack = NULL;
	}

	/* Pushes item to a stack pointed by parameter stack. Returns 0 if succesful,
	 * -1 otherwise.
	 */
	int stack_push(void *p, stack_s *stack){
	 	stack_node_s *newitem = malloc(sizeof(stack_node_s));
		if (!newitem) return -1;
		newitem->value = p;
		newitem->next = *stack;
		*stack = newitem;
		return 0;
	}

	/* Pops item from a stack pointed by parameter stack. Returns pointer to
	 * element removed from stack if succesful, null if there is an error or
	 * the stack is empty.
	 */
	void *stack_pop(stack_s *stack){
		if(!*stack) return NULL;
		stack_node_s *freethis = *stack; 
		void *returnp = freethis->value;
		*stack = (*stack)->next;
		free(freethis);
		return returnp;
	}

	int isDir(char *dirname){
	  struct stat stbuf;
	  stat(dirname, &stbuf);
	  return S_ISDIR(stbuf.st_mode);
	}

	time_t mtime(char *dirname){
	  struct stat stbuf;
	  stat(dirname, &stbuf);
	  return stbuf.st_mtime;
	}

	void checkDir(char* path, stack_s **stack, items *list ){
	  DIR *stream;
	  char fullpath[MAX_PATH_LENGTH];

	  if(!(stream = opendir(path))){
	    return;
	  }
	  struct dirent *dir;
	  while((dir = readdir(stream))){
	    strcpy(fullpath, path);
	    strcat(fullpath, "/");
	    if(strcmp(dir->d_name, ".") && strcmp(dir->d_name, "..")){
	      char *savedpath = (char*) malloc(sizeof(char)*MAX_ITEM_LENGTH);
	      strcat(fullpath, dir->d_name);
	      strcpy(savedpath,fullpath);
	      if(isDir(savedpath)){
		list->dirs[(list->dircnt)++] = savedpath;
		stack_push(savedpath,stack);
	      }
	      else{
		file_n *new = (file_n*) malloc(sizeof(file_n*));
		list->files[(list->filecnt)] = new;
		(list->files[(list->filecnt)])->name = savedpath;
		(list->files[(list->filecnt)])->mtime = mtime(savedpath);
		(list->filecnt)++;
	      }
	    }
	  }
	  closedir(stream);
	  char *popped;
	  while(popped = (char*)stack_pop(stack)){ 
	    checkDir(popped,stack,list);
	  }
	}

	int qsortcbdir(const void* a, const void* b){
	    const char **ia = (const char **)a;
	    const char **ib = (const char **)b;
	    return strcmp(*ia, *ib);
	}

	int qsortcbfile(const void* a, const void* b){
	    const file_n **ia = (const file_n **)a;
	    const file_n **ib = (const file_n **)b;
	    int timea = (int) (**ia).mtime;
	    int timeb = (int) (**ib).mtime;
	    if(timea == timeb)
	      return strcmp((**ia).name, (**ib).name);
	    return timea - timeb;
	}
	
	int main(int argc, char* argv[]){
	  if(argc != 2){
	    printf("Incorrect number of arguments, exiting.\n");
	    return -1;
	  }
	  stack_s stack;
	  stack_init(&stack);
	  items *list = (items*)malloc(sizeof(items));
	  list->dircnt = (list->filecnt = 0);
	  memset(list->dirs, 0, sizeof(char*)*MAX_ITEM_CNT);
	  memset(list->files, 0, sizeof(char*)*MAX_ITEM_CNT);
	  checkDir(argv[1], &stack, list);

	  qsort(list->dirs,list->dircnt,sizeof(char*), &qsortcbdir);
	  for(int i=0;i < list->dircnt;i++){
	    printf("%s\n", list->dirs[i]);
	    free(list->dirs[i]);
	  }
	  printf("---\n");

	  qsort(list->files,list->filecnt,sizeof(file_n*), &qsortcbfile);
	  for(int i=0;i < list->filecnt;i++){
	    printf("path: %s, mtime: %s", (list->files[i])->name, ctime(&((list->files[i])->mtime)));
	    free((list->files[i])->name);
	    free(list->files[i]);
	  }
	  free(list);

	  return EXIT_SUCCESS;
	}
Valgrind: Invalid read/write of size 8
===

I'm a newbie C student trying to write a directory tree. It's working no problem, but Valgrind doesn't approve. I've read posts on similar problems, but can't seem to figure it out.

I would greatly appriciate answers with not only a snippet to make it work, but also an explanation what I'm doing wrong so I won't have the same problem in the future. Feedback on why the code is bad in general won't be overlooked either :)

These are the errors from Valgrind (multiplied by amount of items handled):

	==10463== Invalid write of size 8
	==10463==    at 0x400C5D: checkDir (dirtree.c:96)
	==10463==    by 0x400F53: main (dirtree.c:135)
	==10463==  Address 0x51f88d8 is 0 bytes after a block of size 8 alloc'd
	==10463==    at 0x4C28F9F: malloc (vg_replace_malloc.c:236)
	==10463==    by 0x400BED: checkDir (dirtree.c:93)
	==10463==    by 0x400F53: main (dirtree.c:135)

	==10463== Invalid read of size 8
	==10463==    at 0x4ECFF28: __tz_convert (tzset.c:627)
	==10463==    by 0x4ECD728: ctime (ctime.c:32)
	==10463==    by 0x401022: main (dirtree.c:147)
	==10463==  Address 0x51f88d8 is 0 bytes after a block of size 8 alloc'd
	==10463==    at 0x4C28F9F: malloc (vg_replace_malloc.c:236)
	==10463==    by 0x400BED: checkDir (dirtree.c:93)
	==10463==    by 0x400F53: main (dirtree.c:135)

And her's the code (stripped of stack code):

    #include <stdio.h>
	#include <stdlib.h>
	#include <string.h>
	#include <time.h>

	#include <sys/types.h>
	#include <sys/stat.h>
	#include <unistd.h>
	#include <dirent.h>

	#define MAX_PATH_LENGTH 500
	#define MAX_ITEM_LENGTH 5000
	#define MAX_ITEM_CNT 1000

	typedef struct dirent dirent;
	typedef struct file_s {
	  char *name;
	  time_t mtime;
	} file_n;
	typedef struct itemss {
	  int filecnt;
	  file_n *files[sizeof(char*)*MAX_ITEM_CNT];
	  int dircnt;
	  char *dirs[sizeof(char*)*MAX_ITEM_CNT];              
	} items;
	typedef stack_node_s* stack_s;

	void stack_init(stack_s *stack){
		*stack = NULL;
	}

	/* Pushes item to a stack pointed by parameter stack. Returns 0 if succesful,
	 * -1 otherwise.
	 */
	int stack_push(void *p, stack_s *stack){
	 	stack_node_s *newitem = malloc(sizeof(stack_node_s));
		if (!newitem) return -1;
		newitem->value = p;
		newitem->next = *stack;
		*stack = newitem;
		return 0;
	}

	/* Pops item from a stack pointed by parameter stack. Returns pointer to
	 * element removed from stack if succesful, null if there is an error or
	 * the stack is empty.
	 */
	void *stack_pop(stack_s *stack){
		if(!*stack) return NULL;
		stack_node_s *freethis = *stack; 
		void *returnp = freethis->value;
		*stack = (*stack)->next;
		free(freethis);
		return returnp;
	}

	int isDir(char *dirname){
	  struct stat stbuf;
	  stat(dirname, &stbuf);
	  return S_ISDIR(stbuf.st_mode);
	}

	time_t mtime(char *dirname){
	  struct stat stbuf;
	  stat(dirname, &stbuf);
	  return stbuf.st_mtime;
	}

	void checkDir(char* path, stack_s **stack, items *list ){
	  DIR *stream;
	  char fullpath[MAX_PATH_LENGTH];

	  if(!(stream = opendir(path))){
	    return;
	  }
	  struct dirent *dir;
	  while((dir = readdir(stream))){
	    strcpy(fullpath, path);
	    strcat(fullpath, "/");
	    if(strcmp(dir->d_name, ".") && strcmp(dir->d_name, "..")){
	      char *savedpath = (char*) malloc(sizeof(char)*MAX_ITEM_LENGTH);
	      strcat(fullpath, dir->d_name);
	      strcpy(savedpath,fullpath);
	      if(isDir(savedpath)){
		list->dirs[(list->dircnt)++] = savedpath;
		stack_push(savedpath,stack);
	      }
	      else{
		file_n *new = (file_n*) malloc(sizeof(file_n*));
		list->files[(list->filecnt)] = new;
		(list->files[(list->filecnt)])->name = savedpath;
		(list->files[(list->filecnt)])->mtime = mtime(savedpath);
		(list->filecnt)++;
	      }
	    }
	  }
	  closedir(stream);
	  char *popped;
	  while(popped = (char*)stack_pop(stack)){ 
	    checkDir(popped,stack,list);
	  }
	}

	int qsortcbdir(const void* a, const void* b){
	    const char **ia = (const char **)a;
	    const char **ib = (const char **)b;
	    return strcmp(*ia, *ib);
	}

	int qsortcbfile(const void* a, const void* b){
	    const file_n **ia = (const file_n **)a;
	    const file_n **ib = (const file_n **)b;
	    int timea = (int) (**ia).mtime;
	    int timeb = (int) (**ib).mtime;
	    if(timea == timeb)
	      return strcmp((**ia).name, (**ib).name);
	    return timea - timeb;
	}
	
	int main(int argc, char* argv[]){
	  if(argc != 2){
	    printf("Incorrect number of arguments, exiting.\n");
	    return -1;
	  }
	  stack_s stack;
	  stack_init(&stack);
	  items *list = (items*)malloc(sizeof(items));
	  list->dircnt = (list->filecnt = 0);
	  memset(list->dirs, 0, sizeof(char*)*MAX_ITEM_CNT);
	  memset(list->files, 0, sizeof(char*)*MAX_ITEM_CNT);
	  checkDir(argv[1], &stack, list);

	  qsort(list->dirs,list->dircnt,sizeof(char*), &qsortcbdir);
	  for(int i=0;i < list->dircnt;i++){
	    printf("%s\n", list->dirs[i]);
	    free(list->dirs[i]);
	  }
	  printf("---\n");

	  qsort(list->files,list->filecnt,sizeof(file_n*), &qsortcbfile);
	  for(int i=0;i < list->filecnt;i++){
	    printf("path: %s, mtime: %s", (list->files[i])->name, ctime(&((list->files[i])->mtime)));
	    free((list->files[i])->name);
	    free(list->files[i]);
	  }
	  free(list);

	  return EXIT_SUCCESS;
	}