我是一名尝试编写目录树的新手C学生。它没有问题,但Valgrind不赞成。我已经阅读了类似问题的帖子,但似乎无法弄明白。
我会大大提高答案的答案,不仅要使其成功,还要解释我做错了所以我将来不会遇到同样的问题。关于代码一般不好的原因的反馈也不会被忽视:)
这些是Valgrind的错误(乘以处理的项目数量):
==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)
她的代码(剥离了堆栈代码):
#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;
}
答案 0 :(得分:5)
您只为指针file_n
分配足够的空间:
file_n *new = (file_n*) malloc(sizeof(file_n*));
正确的方法是这样做(并抛弃演员阵容,这是不必要的):
file_n *new = malloc(sizeof(file_n));