【问题标题】:Why this output from perror?为什么这个 perror 的输出?
【发布时间】:2013-02-21 19:18:17
【问题描述】:

我以前从未见过:

上面的左下角是什么?该程序的最新版本是

#include <stdio.h>
#include <stdlib.h> 
int main(int argc, char **argv)
{
   int ch;
   char file_name[25] = "/proc/scsi/scsi";
   FILE *fp; 
   fp = fopen(file_name,"r"); // read mode 
   if (fp == NULL)
   {
      perror(file_name);
      exit(EXIT_FAILURE);
   } 
   printf("The contents of %s file are :\n", file_name); 
   while ((ch = fgetc(fp)) != EOF)
      putchar(ch); 
   fclose(fp);
   return 0;
}

测试

$ cc driveinfo.c;./a.out 
The contents of /proc/scsi/scsi file are :
Attached devices:
Host: scsi0 Channel: 00 Id: 00 Lun: 00
  Vendor: ATA      Model: WDC WD2500JS-75N Rev: 10.0
  Type:   Direct-Access                    ANSI  SCSI revision: 05
Host: scsi1 Channel: 00 Id: 00 Lun: 00
  Vendor: ATA      Model: ST3250824AS      Rev: 3.AD
  Type:   Direct-Access                    ANSI  SCSI revision: 05
Host: scsi2 Channel: 00 Id: 00 Lun: 00
  Vendor: TSSTcorp Model: DVD+-RW TS-H653A Rev: D300
  Type:   CD-ROM                           ANSI  SCSI revision: 05
Host: scsi3 Channel: 00 Id: 00 Lun: 00
  Vendor: Optiarc  Model: DVD-ROM DDU1681S Rev: 102A
  Type:   CD-ROM                           ANSI  SCSI revision: 05
Host: scsi4 Channel: 00 Id: 00 Lun: 00
  Vendor: Lexar    Model: USB Flash Drive  Rev: 1100
  Type:   Direct-Access                    ANSI  SCSI revision: 00
Host: scsi5 Channel: 00 Id: 00 Lun: 00
  Vendor: WD       Model: 5000AAKB Externa Rev: l108
  Type:   Direct-Access                    ANSI  SCSI revision: 00

下面重现了奇怪的输出:

#include <stdio.h>
#include <stdlib.h> 
int main(int argc, char **argv)
{
   int ch;
   char file_name[25] = "/proc/scsi/scsi-notExist";
   FILE *fp; 
   fp = fopen(file_name,"r"); // read mode 
   if (fp == NULL)
   {
      perror(&file_name[25]);
      exit(EXIT_FAILURE);
   } 
   printf("The contents of %s file are :\n", file_name); 
   while ((ch = fgetc(fp)) != EOF)
      putchar(ch); 
   fclose(fp);
   return 0;
}

更新

clang 编译器会发出警告,但 (g)cc 不会:

$ clang -Wconversion cpu-disk-info.c
cpu-disk-info.c:14:15: warning: array index of '25' indexes past the end of an
      array (that contains 16 elements) [-Warray-bounds]
      perror(&file_name[25]);
              ^         ~~
cpu-disk-info.c:6:4: note: array 'file_name' declared here
   char file_name[] = "/proc/scsi/scsi";
   ^
1 warning generated.
dev@dev-OptiPlex-745:~$ gcc -Wconversion cpu-disk-info.c
dev@dev-OptiPlex-745:~$ 

【问题讨论】:

  • 我见过一次。我认为它试图打印一个没有“视觉表示”的字节。
  • 看起来file_name 包含一些垃圾。所以 a) 找不到文件,b) file_name 的内容无法正确打印。你能重新创建错误的输出吗?
  • 嗯,当你通过file_name 时,它工作得很好,对吧?我认为在图像中,如果你通过了file_name[25],那件事会更有意义,因为它是NULL 字节。
  • 传递一个file_name 是一个\0 可以正常工作,因为它是一个有效的字符串。虽然file_name[25] 会超出范围,并且可能会崩溃或导致垃圾。
  • 是的!很好看! file_name[25] 越界。

标签: c linux gcc clang cc


【解决方案1】:

这很可能是由于没有将有效的 const char* 传递给 void perror(const char *s),导致 &lt;filename&gt;: No such file or directory 中的文件名输出为垃圾/不可打印字符。

perror() 函数应将通过符号 errno 访问的错误号映射到与语言相关的错误消息,该错误消息应写入标准错误流,如下所示:

首先(如果s不是空指针且s指向的字符不是空字节),s指向的字符串后跟冒号和a。

然后是一个错误消息字符串,后跟一个 .

【讨论】:

  • 我可以用&amp;file_name[25]to perror 重现错误,它编译时没有警告并显示垃圾。我希望这与你所说的一致。我用我的发现更新了这个问题。谢谢!
  • @NickRosencrantz 是的,perror(&amp;file_name[25]); 是一个指向字符串第 26 个字符的指针,它超出了范围,不是要传入的有效字符指针。
  • clang 编译器会发出警告,但不会发出 (g)cc。我再次更新了我的发现。感谢您的信息。我正在学习 C 和编译器。
【解决方案2】:

我认为您更正了警告 driveinfo.c:17 或发布您的代码。 还可以;)

祝你好运!

【讨论】:

    【解决方案3】:

    "varning att scicka heltal utan konvertering ..." 听起来像是对perror 的调用,可能不是字符串?

    如果您发布代码,我们可能会看得更清楚,但我很确定警告和输出是相关的。

    编辑:如果您将filename[25] 传递给该函数,我预计会出现此警告。如果您传递&amp;filename[25],那么您可能传递的根本不是字符串,因此会打印一些随机字节,这几乎可以打印任何内容。

    【讨论】:

    猜你喜欢
    • 2022-11-16
    • 2021-04-06
    • 2012-07-17
    • 2016-05-23
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多