2012-03-30 68 views
2

我是一名試圖編寫目錄樹的新手C學生。它工作沒問題,但Valgrind不贊同。我已閱讀關於類似問題的帖子,但似乎無法弄清楚。Valgrind:無效的讀寫大小爲8

我會大大appriciate答案不僅一個片段,使其工作,但也是一個解釋我做錯了,所以我不會在未來有同樣的問題。爲什麼代碼是一般的差反饋不會忽視任何:)

這些是從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; 
} 

回答

5

你只file_n分配的指針足夠的空間:

file_n *new = (file_n*) malloc(sizeof(file_n*)); 

正確的方法是做到這一點(和離開了劇組,這是不必要的):

file_n *new = malloc(sizeof(file_n)); 
+3

或者交替,'file_n *新的=的malloc(*的sizeof新);' – caf 2012-03-31 02:43:40