【问题标题】:Segmentation fault when reading command line arguments读取命令行参数时出现分段错误
【发布时间】:2010-03-31 22:22:32
【问题描述】:
#include<stdio.h>
#include<zlib.h>
#include<unistd.h>
#include<string.h>


int main(int argc, char *argv[])
{
   char *path=NULL;
   size_t size;
   int index ;
   printf("\nArgument count is = %d", argc);
   printf ("\nThe 0th argument to the file is %s", argv[0]);
   path = getcwd(path, size);
   printf("\nThe current working directory is = %s", path);
   if (argc <= 1)
   {
      printf("\nUsage: ./output filename1 filename2 ...");
   }
   else if (argc > 1)
   {
      for (index = 1; index <= argc;index++)
      {
            printf("\n File name entered is = %s", argv[index]);
            strcat(path,argv[index]);
            printf("\n The complete path of the file name is = %s", path);
      }
   }
   return 0;
}

在上面的代码中,这是我在运行代码时得到的输出:

$ ./output test.txt

Argument count is = 2
The 0th argument to the file is ./output
The current working directory is = /home/welcomeuser
 File name entered is = test.txt
 The complete path of the file name is = /home/welcomeusertest.txt
Segmentation fault (core dumped)

任何人都可以请我理解为什么我会收到核心转储错误吗?

【问题讨论】:

    标签: c segmentation-fault


    【解决方案1】:

    你说index &lt;= argc 结束了argv。那应该是index &lt; argc。请记住,数组索引从 比数组的长度小一

    (从1开始是正确的,因为argv[0]是程序名。)

    【讨论】:

      【解决方案2】:

      strcat 无效。它正在尝试将数据连接到 C 运行时库调用返回的缓冲区。您需要使用自己的缓冲区。并且您需要以您使用它的方式在 getcwd() 返回的缓冲区上使用 free() (传入 NULL 会导致它分配内存)。

      【讨论】:

      • 嗨,马克,请您详细说明您的观察。我是在 C 上处理字符串操作和文件操作的新手。任何能帮助我理解你所指出的内容的好资源都将受到高度赞赏。问候,小黑
      • @darkie:我正在查看 linux 机器上的手册页,它表明如果给定缓冲区为 NULL,getcwd 会使用 malloc 分配缓冲区。 (linux.die.net/man/3/getcwd)。不过,它似乎取决于版本。但是,返回的缓冲区可能不够长,无法添加新数据。 strcat 会将新数据添加到该缓冲区并覆盖分配的空间。
      【解决方案3】:

      getcwd()path 分配一个大小等于size 的缓冲区。您没有初始化 size 变量。将它设置得足够大以容纳整个路径和名称,这应该可以工作。如果缓冲区不够大,strcat() 将写入缓冲区的末尾,覆盖堆栈上的其他值(可能包括函数返回指针,这会导致return 出现段错误)。

      另外,getcwd() 使用malloc() 分配您分配给path 的缓冲区。当你完成它时,free() 这个缓冲区会很好。虽然这在程序结束时并不是绝对必要的 - 因为系统无论如何都会回收内存。

      您的代码中也存在一些逻辑错误。首先,argv 数组索引范围从 0 到 argc-1。您的for 循环退出条件使您读取argv 数组末尾的一个元素

      请注意,strcat() 将在每次迭代将新参数附加到上一次迭代的结果。这意味着调用 /home$ ./output foo bar baz 最终会得到:

      The complete path of the file name is = /home/foo
      The complete path of the file name is = /home/foobar
      The complete path of the file name is = /home/foobarbaz
      

      这可能不是你想要的:)。 (省略输出中不相关的行)。

      【讨论】:

      • @Fred Larson:刚刚搜索了联机帮助页 - 你是对的。虽然这是一个非标准的 glibc 扩展。现在这解释了为什么它没有在一开始就出现段错误;)。
      【解决方案4】:

      虽然关于strcat 的答案是有效的,但考虑到您的程序崩溃的问题是NULL 指针延迟,因为您使用&lt;= argc 而不是&lt; argc

      在 C 中,argv[argc] 是一个 NULL 指针。

      【讨论】:

        【解决方案5】:

        您正在阅读argv 的结尾。不要那样做。停在argc-1'th 参数处。

        【讨论】:

          【解决方案6】:

          strcat(path,argv[index]) 正在向一个不足以容纳额外数据的缓冲区添加数据。

          您应该传入一个size 值,以确保缓冲区足够大。你也没有初始化size,所以你真的不知道将返回什么大小的缓冲区(所有这些都是假设你使用的是getcwd()的GNU libc版本,如果你传入,它将分配一个缓冲区空)。

          【讨论】:

          • 显然您的代码中至少有 2 个错误。 RichieHindle、Donal Fellows 和 Charles Bailey 发现了另一个严重问题。
          • 嗨,Michael,我是 C 中的字符串和文件操作的新手。任何能帮助我理解这里需要做什么的好资源都将受到高度赞赏。问候,小黑
          • K & R C 书籍仍然是黄金标准。
          猜你喜欢
          • 1970-01-01
          • 2020-09-03
          • 2020-09-16
          • 2014-05-29
          • 2018-08-19
          • 1970-01-01
          • 2017-09-18
          • 1970-01-01
          相关资源
          最近更新 更多