Почему происходит сбой в работе моей программы, когда я пытаюсь читать из каталога? - PullRequest
0 голосов
/ 19 октября 2018

Когда я запускаю свою программу с аргументами ./a.out и именем каталога в качестве аргументов, я получаю ошибку сегментации после того, как впервые печатаю «сделал это» на терминале и когда я пытаюсь прочитать из каталога (я знаюэто потому, что второй "сделал это" никогда не печатается).Я предполагаю, что это проблема с указателем, но не знаю, почему.Некоторые из проблем были исправлены благодаря совету комментаторов ниже.Я обновил этот пост с тех пор.

Почему я получаю это?Я пытался решить проблему с помощью 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 голосов
/ 19 октября 2018

Вы используете node *head=malloc( sizeof( node*))', когда вы, вероятно, хотите использовать sizeof( node) для этого последнего распределения.После этого присваивание head-> abs вызывает неопределенное поведение.

0 голосов
/ 19 октября 2018

Это неправильно:

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

Это должно быть sizeof(node).

В результате вы выделяете достаточно места только для одного указателя, но вам нужно достаточно места для4 указателя.

...