C 使用stat(st_uid)的分段故障(堆芯转储)

C 使用stat(st_uid)的分段故障(堆芯转储),c,linux,unix,stat,dirent.h,C,Linux,Unix,Stat,Dirent.h,我想在UNIX中编写一个简单的C脚本,它的工作方式类似于“ls-l”。我有一个工作部分,其中脚本列出了当前目录中的所有文件: #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <dirent.h> #include <sys/types.h> int main(int argc, char *argv[]) { DIR *katalog; str

我想在UNIX中编写一个简单的C脚本,它的工作方式类似于“ls-l”。我有一个工作部分,其中脚本列出了当前目录中的所有文件:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>

int main(int argc, char *argv[])
{
 DIR *katalog;
 struct dirent *dir;
 katalog = opendir(".");

if (argc == 1) {
printf("without option");
  if (katalog) {
    while ((dir = readdir(katalog)) {
     printf("%s \n", dir->d_name);
    }
    closedir(katalog);
  }
  return(0);
}    
}
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv[])
{
迪尔*卡塔洛;
结构方向*dir;
katalog=opendir(“.”);
如果(argc==1){
printf(“无选择权”);
伊夫(卡塔洛){
while((dir=readdir(katalog)){
printf(“%s\n”,dir->d_name);
}
closedir(卡塔洛);
}
返回(0);
}    
}
现在我想添加有关st_-gid、st_-uid、st_-size和st_-mtime的信息。我从st_-uid开始。我的代码现在看起来是这样的(它在unix下编译得很好)。不幸的是,它给了我一个错误“分段错误(内核转储)”。我试图在堆栈和Internet中寻找答案,甚至使用了其他线程的一些提示(例如:),但仍然会发生错误…我不知道还有什么可以更改以修复它

以下是产生错误的代码:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h> 

int main(int argc, char *argv[])
{
 DIR *katalog;
 struct dirent *dir;
 katalog = opendir(".");
 struct stat *astat;

if (argc == 1) {
printf("Without option");
  if (katalog) {
    while ((dir = readdir(katalog)) != NULL && astat->st_uid != 0) {
     printf("%s %llu \n", dir->d_name, (unsigned long long)astat->st_uid);
    }
    closedir(katalog);
  }
  return(0);
}
}
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv[])
{
迪尔*卡塔洛;
结构方向*dir;
katalog=opendir(“.”);
结构stat*astat;
如果(argc==1){
printf(“无选择权”);
伊夫(卡塔洛){
while((dir=readdir(katalog))!=NULL&&astat->st_uid!=0){
printf(“%s%llu\n”,dir->d_name,(unsigned long long)astat->st_uid);
}
closedir(卡塔洛);
}
返回(0);
}
}

astat
未在代码中初始化(在while循环中使用)

因为
astat
尚未在
astat->st\u uid
之前初始化/分配,代码显示未定义的行为(UB)。在OP案例中,代码崩溃

不是声明没有值的指针,而是将NNED编码为:

1) 声明一个
struct stat
对象

2) 用一个
*stat()
调用填充它


你好谢谢你的回答。你能详细说明一下吗?我昨天才开始学C。我认为“struct stat*astat;”足以初始化我的变量。当我试图在代码开头设置“astat=0”时,也会发生错误。@BloodyMary您希望指针
astat
struct stat*astat一起具有什么值
?@chux我希望它会接受stat结构中包含的任何值(如图所示),这取决于我将在我的代码中引用哪个字段->在本例中,我使用astat->st\u-uid引用st\u-uid。它适用于目录名(我给出的第一个代码),所以我认为它也适用于用户ID(st_uid),它会显示所有文件,上面的代码+st_uid适用于所有文件。@BloodyMary在
struct stat*astat不存在。在代码行
struct stat*astat之后,您希望指针
astat
具有什么值?它是未初始化的。因此,当代码到达
astat->st_uid
时,
astat
是一个未初始化的值。调用
readdir(katalog)
不会影响
astat
。代码缺少一个*stat()调用和其他东西。@chux我仍然不明白。好的,我将尝试按照man7.org上的代码进行操作,我们在上面链接了一些评论。C对我来说太没吸引力了,没有什么能像我期望的那样工作。。。Python和MATLAB与C语言相比非常简单。生产率提示:启用所有编译器警告并节省时间。我的编译器报告“警告:此函数中可能未初始化就使用了astat”。@chux如何做到这一点?如何在Unix下启用编译器警告?我只是简单地使用命令行和“cc”编译器。它没有给我任何警告提示。也许
gcc-std=c11-O3-pedantic-Wall-Wextra-Wconversion…
。研究你的编译器文档了解更多信息。参见GCC 3.4是一个过时的版本。尝试使用
gcc-Wall-Wextra-g
并阅读我建议的
memset(&sb,0,sizeof(sb))行前执行
lstat
OK。现在它可以工作了,但是它比我最初的代码要复杂得多。我需要逐行检查它以了解所有内容,并在我自己的代码中实现所有统计数据的解决方案。感谢您的时间和所有评论。我真的很感激。@BloodyMary顺便说一句:很好地使用了
%llu
(unsigned long)
来打印
sb.st\u uid
。谁或是什么文本建议的?@chux首先,我使用了其他错误的格式,这给了我一个错误。然后我读到这个:。
int main(int argc, char *argv[]) {
  DIR *katalog;
  struct dirent *dir;
  katalog = opendir(".");

  //struct stat *astat;

  if (argc == 1) {
    printf("Without option");
    if (katalog) {
      while ((dir = readdir(katalog)) != NULL) {
        // add
        struct stat sb;
        if (lstat(dir->d_name, &sb) == -1) {
          perror("lstat");
          exit(EXIT_FAILURE);
        }
        if (sb.st_uid != 0) {
          printf("%s %llu \n", dir->d_name, (unsigned long long) sb.st_uid);
        }
      }
      closedir(katalog);
    }
  }
  return (0);
}