当我尝试从目录读取时,为什么我的程序段错误?

时间:2018-10-18 22:08:15

标签: c valgrind

当我使用./a.out和目录名称作为参数运行程序时,第一次在终端上打印“ make it”并尝试从目录读取时,会遇到分段错误(我知道这是因为第二个“成功”从未被打印出来)。我假设这是一个指针问题,但不确定原因。由于以下评论者的建议,一些问题已得到解决。从那以后我已经更新了这篇文章。

我为什么收到这个?我已经尝试使用valgrind来解决此问题,但是我是完全陌生的,它给我的消息对我来说没有意义。这可能是运行valgrind和下面的代码中最有用的片段:

==26237== Invalid read of size 1
==26237==    at 0x4F1B940: invalid_name (opendir.c:91)
==26237==    by 0x4F1B940: opendir (opendir.c:172)
==26237==    by 0x108DF2: main (DirectorySearch.c:63)
==26237==  Address 0x522d2c0 is 0 bytes inside a block of size 250 free'd
==26237==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26237==    by 0x108D7A: main (DirectorySearch.c:52)
==26237==  Block was alloc'd at
==26237==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26237==    by 0x108C8B: main (DirectorySearch.c:36)
==26237== 
==26237== Syscall param openat(filename) points to unaddressable byte(s)
==26237==    at 0x4F4BDB1: __open_nocancel (open64.c:69)
==26237==    by 0x4F1B952: opendir (opendir.c:190)
==26237==    by 0x108DF2: main (DirectorySearch.c:63)
==26237==  Address 0x522d2c0 is 0 bytes inside a block of size 250 free'd
==26237==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26237==    by 0x108D7A: main (DirectorySearch.c:52)
==26237==  Block was alloc'd at
==26237==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26237==    by 0x108C8B: main (DirectorySearch.c:36)


/*
   Lists directory contents recursively, breadth first.
*/

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

typedef struct {
    char* name;            
    char* abs;            
    struct node* next;
    struct node* prev;
} node;

node* append(node*, char*, char*);
int print_list(node*);

int main(int argc, char** argv) {

    if(argc != 2){
        printf("You must provide 2 arguments: <./filename> <directory>\n");
        return 0;
    }

    DIR* dp;              
    struct dirent* dirp;  
    struct stat buff;
    char* name = malloc(250 * sizeof(char));
    char* abs = malloc(250 * sizeof(char));
    char* tmp = malloc(250 * sizeof(char));
    node* head = malloc(sizeof(node));
    if((chdir(argv[1])) == -1) {
        fprintf(stderr, "%s\n", strerror(errno));
        exit(errno);
    }
    head->name = argv[1];
    head->abs = getcwd(tmp, 250);
    head->next = NULL;
    printf("%s\n", tmp);

    free(name);    
    free(abs);
    free(tmp);

    int firstDir = 0;

    do {
        if(firstDir > 0) {
            if (chdir(head->abs) == -1) {
                fprintf(stderr, "%s\n", strerror(errno));
                exit(errno);
            }
        } 
        dp = opendir(head->abs);
        printf("%s\n", "made it");
        while((dirp = readdir(dp)) != NULL)          
        {
            printf("%s\n", "made it");
            lstat(dirp->d_name, &buff);
            if(S_ISREG(buff.st_mode)) 
                printf("regular file: %s\n", dirp->d_name);
            else if(S_ISDIR(buff.st_mode) && !S_ISLNK(buff.st_mode)) {
                if (((strcmp(dirp->d_name, "..")) != 0) && ((strcmp(dirp->d_name, ".")) != 0)) {
                    printf("directory: %s\n", dirp->d_name);

                    name = calloc(250, sizeof(char));
                    abs  = calloc(250, sizeof(char));
                    tmp  = calloc(250, sizeof(char));                

                    strncpy(name, dirp->d_name, strlen(dirp->d_name));

                    abs = getcwd(tmp, 250);
                    tmp = abs;

                    asprintf(&abs, "%s/%s", tmp, dirp->d_name);

                    head = append(head, name, abs);
                    free(name);
                    free(tmp);
                }else 
                    printf("directory: %s\n", dirp->d_name);

            } 
            else if (S_ISLNK(buff.st_mode))
                printf("%s %s\n", "LINK:      ", dirp->d_name);
            else if (S_ISFIFO(buff.st_mode))
                printf("%s %s\n", "FIFO:      ", dirp->d_name);
            else if (S_ISCHR(buff.st_mode))
                printf("%s %s\n", "CHAR DEV:  ", dirp->d_name);
            else if (S_ISBLK(buff.st_mode))
                printf("%s %s\n", "BLOCK DEV: ", dirp->d_name);
            else if (S_ISSOCK(buff.st_mode))
                printf("%s %s\n", "SOCKET:    ", dirp->d_name);
            else 
                printf("%s\n", "Unknown file type.");
        }                                     
        head = head->next;
        if (head != NULL) {free(head->prev);}
        printf("\n");

        firstDir++;

    } while (head != NULL);                 

    free(abs);

    return 0;
}

node* append(node* head, char *name, char *abs)
{
    node* new = malloc(sizeof(node));
    node* cursor = head;                      

    while(cursor->next != NULL)          
        cursor = cursor->next;      

    node* prev = cursor;

    new->name = name;
    new->abs = abs;
    new->next = NULL;
    new->prev = prev;

    cursor->next = new;

    return head;                         
}

2 个答案:

答案 0 :(得分:3)

当您可能想为上一次分配使用node *head=malloc( sizeof( node*))'时,您正在使用sizeof( node)。此后,分配给head-> abs会调用未定义的行为。

答案 1 :(得分:1)

这是错误的:

node* head = malloc(sizeof(node*));

应为sizeof(node)

结果,您只为一个指针分配了足够的空间,但为4个指针分配了足够的空间。