2012-03-30 9 views
2

Ich bin ein Neuling C Student versucht, einen Verzeichnisbaum zu schreiben. Es funktioniert kein Problem, aber Valgrind ist nicht einverstanden. Ich habe Beiträge zu ähnlichen Problemen gelesen, kann es aber nicht herausfinden.Valgrind: Ungültige lesen/schreiben der Größe 8

Ich würde Antworten mit nicht nur einem Ausschnitt sehr schätzen, um es zu arbeiten, aber auch eine Erklärung, was ich falsch mache, also werde ich nicht das gleiche Problem in der Zukunft haben. Feedback darüber, warum der Code ist schlecht im Allgemeinen wird nicht entweder übersehen :)

Dies sind die Fehler von Valgrind (multipliziert mit Menge Artikel behandelt):

==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) 

Und sie ist der Code (beraubt 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; 
} 

Antwort

5

Sie sind nur genügend Platz für einen Zeiger auf file_n Zuweisung:

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

Der richtige Weg ist, dies zu tun (und die Besetzung auslassen, dann ist es nicht notwendig):

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

oder alternativ 'file_n * new = malloc (sizeof * neu);' – caf

Verwandte Themen