提问人:owen.H 提问时间:11/15/2023 最后编辑:UpAndAdamowen.H 更新时间:11/15/2023 访问量:57
我正在创建自己的 ls 版本,但我被段错误卡住了
I am creating my own version of ls in and I'm stuck with a segfault
问:
这是我制作的代码,我创建了一个时间函数来获取文件的创建日期,然后获取所有权限,然后我将它们全部放在一个名为的函数中,它就在这里段错误ls -l
get_permission
my_ls_l
void get_time(char *str)
{
str[16] = '\0';
str = str + 4;
mini_printf("%s",str);
}
void get_permission(struct stat stat )
{
my_putchar((S_ISDIR(stat.st_mode)) ? 'd' :
(S_ISBLK(stat.st_mode) ? 'b' :
(S_ISCHR(stat.st_mode) ? 'c' : '-')));
my_putchar((stat.st_mode & S_IRUSR) ? 'r' : '-');
my_putchar((stat.st_mode & S_IWUSR) ? 'w' : '-');
my_putchar((stat.st_mode & S_IXUSR) ? 'x' : '-');
my_putchar((stat.st_mode & S_IRGRP) ? 'r' : '-');
my_putchar((stat.st_mode & S_IWGRP) ? 'w' : '-');
my_putchar((stat.st_mode & S_IXGRP) ? 'x' : '-');
my_putchar((stat.st_mode & S_IROTH) ? 'r' : '-');
my_putchar((stat.st_mode & S_IWOTH) ? 'w' : '-');
my_putchar((stat.st_mode & S_IXOTH) ? 'x' :
(stat.st_mode & S_ISVTX) ? 'T' : '-');
}
int my_ls_l(void)
{
struct dirent *entry;
DIR *dir;
struct stat stat;
struct passwd *pw = getpwuid(stat.st_uid);
struct group *grp = getgrgid(stat.st_gid);
dir = opendir("./");
while ((entry = readdir(dir)) != NULL) {
if (entry->d_name[0] != '.') {
get_permission(stat);
mini_printf("%s", entry->d_name);
mini_printf("%s",stat.st_nlink);
mini_printf("%s",entry->d_name_name);
mini_printf("%s",grp->gr_name);
mini_printf("%s",stat.st_size);
get_time(ctime(&stat.st_mtime));
mini_printf("\n");
}
}
mini_printf("\n");
closedir(dir);
}
int main(void) {
my_ls_l();
return (0);
}
我试图在这里做ls -l,它得到文件的名称,然后它出现段错误,我不明白为什么
答:
2赞
Refugnic Eternium
11/15/2023
#1
您的代码中有多个问题。
最明显的一个是,你既不填充你的结构,也不初始化它,这意味着该结构的每个属性都可以具有任何可能的值。(这使得它毫无用处)。stat
你想要的是函数(https://www.man7.org/linux/man-pages/man2/stat.2.html),如下所示:stat
int my_ls_l(void)
{
struct dirent *entry;
DIR *dir;
struct stat st;
dir = opendir("./");
while ((entry = readdir(dir)) != NULL) {
if (entry->d_name[0] != '.'
&& !stat(entry->d_name, &st)
) {
struct passwd *pw = getpwuid(st.st_uid);
struct group *grp = getgrgid(st.st_gid);
get_permission(stat);
mini_printf("%s", entry->d_name);
mini_printf("%s",st.st_nlink);
mini_printf("%s",entry->d_name_name);
mini_printf("%s",grp->gr_name);
mini_printf("%s",st.st_size);
get_time(ctime(&st.st_mtime));
mini_printf("\n");
}
}
mini_printf("\n");
closedir(dir);
}
始终检查此类函数的返回值。
此外,最好将绝对路径传递给 ,但对于初学者来说,相对路径应该可以。stat
另一个(潜在)问题是您使用 .
您正在写入未知大小的缓冲区,该缓冲区可以在任何给定时间被覆盖。ctime
使用此类缓冲区时,请将内容复制到您知道其大小的缓冲区中,然后使用该缓冲区。
你的 gettime 函数可以像这样优化:
void get_time(char *str)
{
mini_printf("%s",str + 4);
}
这是有效的,因为您不是在操作缓冲区,而是将其“复制”到输出流,从第 4 个字符开始。 可以合理地假设 ctime 缓冲区中的字符串已经以 0 结尾。
另一方面:通过调试器运行代码。它将帮助您比我们在 StackOverflow 上更快地发现错误。它将帮助你学会比我们更好地帮助自己。
评论
0赞
owen.H
11/15/2023
好的,谢谢你,我会按照你说的去做
评论
ctime
The returned value points to an internal array whose validity or value may be altered by any subsequent call to asctime or ctime.
struct passwd *pw = getpwuid(stat.st_uid);
...但是在代码的这一点上,结构是未初始化的。你做事的顺序很重要。stat
stat
在代码中的每个点都未初始化。