c:ls -l实现提供未定义的行为

时间:2016-11-23 01:01:46

标签: c

因此,对于赋值,我需要在c中实现ls -l功能。我试图将所有信息都放入一个字符串数组中,以便以后可以操作数据。它在while循环中打印出来很好,但如果我尝试打印我的内容数组,那么它就会中断。什么会导致这个错误?

int getContentsLong(const char *dir, char **contents)
{
    DIR *dp = NULL;
    struct dirent *dptr = NULL;
    struct stat fileStat;

    if (dir == NULL)
    {
        printf("ERROR\n");
        return -1;  
    }   
    dp = opendir(dir);
    if (dp == NULL)
    {
        printf("ERROR\n");
        return -1;
    }
    int cnt = 0;
    char toRtn[512];
    char path[256];
    while ((dptr = readdir(dp)) != NULL)
    {   
        strcpy(path, dir);
        strcat(path, "/");
        strcat(path, dptr->d_name);
        stat(path, &fileStat);
        strcpy(path, " ");

        //getting l info
        //permissions
        toRtn[0] =    ((S_ISDIR(fileStat.st_mode)) ? 'd' : '-');
        strcat(toRtn, (fileStat.st_mode & S_IRUSR) ? "r" : "-");
        strcat(toRtn, (fileStat.st_mode & S_IWUSR) ? "w" : "-");
        strcat(toRtn, (fileStat.st_mode & S_IXUSR) ? "x" : "-");
        strcat(toRtn, (fileStat.st_mode & S_IRGRP) ? "r" : "-");
        strcat(toRtn, (fileStat.st_mode & S_IWGRP) ? "w" : "-");
        strcat(toRtn, (fileStat.st_mode & S_IXGRP) ? "x" : "-");
        strcat(toRtn, (fileStat.st_mode & S_IROTH) ? "r" : "-");
        strcat(toRtn, (fileStat.st_mode & S_IWOTH) ? "w" : "-");
        strcat(toRtn, (fileStat.st_mode & S_IXOTH) ? "x" : "-");
        strcat(toRtn, " ");

        //links
        char tmp[sizeof(long int)];
        sprintf(tmp, "%d", fileStat.st_nlink); 
        strcat(toRtn, tmp);
        strcat(toRtn, " ");

        //owner and group names
        struct passwd *pw = getpwuid(fileStat.st_uid);
        struct group  *gr = getgrgid(fileStat.st_gid);      
        if (pw != 0) strcat(toRtn, pw->pw_name);
        strcat(toRtn, " ");
        if (gr != 0) strcat(toRtn, gr->gr_name);
        strcat(toRtn, " ");

        //filesize
        strcpy(tmp, " ");
        sprintf(tmp, "%ld", fileStat.st_size);
        strcat(toRtn, tmp);
        strcat(toRtn, " "); 

        //last access time
        strcpy(tmp, " ");
        strftime(tmp, 200, "%b %d %H:%M", localtime(&fileStat.st_atime));
        strcat(toRtn, tmp);
        strcat(toRtn, " ");

        //file/dir name
        strcat(toRtn, dptr->d_name);
        strcat(toRtn, " ");

        //strcpy(contents[cnt], toRtn);
        contents[cnt] = toRtn;  
        printf("%s\n", contents[cnt]);  

        strcpy(toRtn, " ");
        cnt++;
    }
    return cnt;
}

我从

获得的输出
   printf("%s\n", contents[cnt]); 

行是:

drwxr-xr-x 30 justin justin 4096 Nov 22 20:18 .. 
drwxr-xr-x 2 justin justin 4096 Nov 22 20:18 . 
-rw-r--r-- 1 justin justin 5676 Nov 22 20:18 ls.c 
-rwxr-xr-x 1 justin justin 12172 Nov 22 20:18 ls

但是当我打印

for (int i = 0; i < cnt; i++)
{
    printf("%s ", contents[i]);
}

它不会显示任何内容。 如果我使用strcpy(content,toRtn);我遇到一个段错误。

2 个答案:

答案 0 :(得分:0)

此代码中可能存在许多错误。这是一个明目张胆的错误:

toRtn[0] =    ((S_ISDIR(fileStat.st_mode)) ? 'd' : '-');
// WAIT what about the NUL terminator?
strcat(toRtn, (fileStat.st_mode & S_IRUSR) ? "r" : "-");

另一个错误在于:

contents[cnt] = toRtn;

所以 contents中的每个条目都会指向toRtn(即contents[0] == contents[1],我确定这不是你想要的),这些将会都是悬空指针(这也不是你想要的)。

首先修复这些错误,也许还有更多错误。

答案 1 :(得分:0)

原因是,对于cnt的各种值。

contents[cnt] = toRtn;  

用于(间接)将toRtn返回给调用者,其中toRtn是函数中的本地数组,因此在函数返回时不再存在。

这意味着,对于调用者来说,循环

for (int i = 0; i < cnt; i++)
{
    printf("%s ", contents[i]);
}

反复尝试打印不再存在的char数组的内容。这给出了未定义的行为。

您的代码中还有其他基本问题。您需要更好地理解指针和数组之间的关系(在某些情况下它们可以互换使用,但是当它们不可互换时,您的某些代码可以互换使用)和范围的含义(将局部变量的地址返回到无论如何,调用者是一个坏主意,因为当包含函数/作用域结束时,变量将不再存在。