迭代 argv[] 会产生分段错误
Iterating over argv[] produces segmentation fault
我正在编写一个程序,它从命令行读取 "flags" 以及程序名称。我希望程序读取多个标志(-i
、-c
和 -n
)并在调用一个标志或标志组合时执行不同的函数。
这是我开始写的代码:
printf("Argv 0: %s\n", argv[0]);
printf("Argv 1: %s\n", argv[1]);
printf("Argv 2: %s\n", argv[2]);
for (int i = 1; i <= argc + 1; i++) {
if (strcmp("-i", argv[i]) == 0) {
printf("%s\n", "found -i");
}
else{
printf("%s\n", "did not find -i");
}
}
只是尝试一个标志(-i
),但我希望它同时读取一个或多个标志并调用相应的函数。
当我执行程序时:
./program-name test -i
Argv 0: test
Argv 1: -i
Argv 2: (null)
found -i
Segmentation fault
为了简化,argc
是命令行参数的个数,参数保存在argv[]
中。由于 C 数组具有基于 0
的索引,因此在您的代码中,您需要更改
for (int i = 1; i <= argc + 1; i++)
到
for (int i = 1; i < argc; i++)
限制对有效参数列表的访问。
要对此添加一点参考,引用 C11
,第 §5.1.2.2.1 章,程序启动(强调我的)
If the value of argc
is greater than zero, the string pointed to by argv[0]
represents the program name; argv[0][0]
shall be the null character if the
program name is not available from the host environment. If the value of argc
is
greater than one, the strings pointed to by argv[1]
through argv[argc-1]
represent the program parameters.
您超出了 argv
的界限; for
循环的条件不正确。应该是 i < argc
.
另外,为什么要重新发明轮子?查看 getopt()
.
不要重做已证明可靠的旧代码。它浪费时间并重复工作。作为一个长期的 C 编码器,我总是(当我记得时)在尝试从头开始之前先查看代码库。我先重新调整用途然后创建。我很聪明,知道在我之前有很多更聪明的编码员。
使用免费且有效的 getopt() 和 getopt_long() 函数为您解析命令行参数。如果您 google 搜索 "getopt example" but here is the GNU C tutorial.
,代码库中有很多示例
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main (int argc, char **argv)
{
int aflag = 0;
int bflag = 0;
char *cvalue = NULL;
int index;
int c;
opterr = 0;
while ((c = getopt (argc, argv, "abc:")) != -1)
switch (c)
{
case 'a':
aflag = 1;
break;
case 'b':
bflag = 1;
break;
case 'c':
cvalue = optarg;
break;
case '?':
if (optopt == 'c')
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
else if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf (stderr,
"Unknown option character `\x%x'.\n",
optopt);
return 1;
default:
abort ();
}
printf ("aflag = %d, bflag = %d, cvalue = %s\n",
aflag, bflag, cvalue);
for (index = optind; index < argc; index++)
printf ("Non-option argument %s\n", argv[index]);
return 0;
}
用你的代码和你的循环,这一行是错误的:
(strcmp("-i", argv[i])
当你将argv[i]传递给strcmp时,你应该确保argv[i]不为NULL。该函数以 NULL 指针作为参数会发生段错误。您应该更好地测试 argv[i] != NULL 或将 i <= argc 放在循环中而不是 i <= argc + 1 ,后者在 argv 字符串数组中包含 NULL 指针。
我正在编写一个程序,它从命令行读取 "flags" 以及程序名称。我希望程序读取多个标志(-i
、-c
和 -n
)并在调用一个标志或标志组合时执行不同的函数。
这是我开始写的代码:
printf("Argv 0: %s\n", argv[0]);
printf("Argv 1: %s\n", argv[1]);
printf("Argv 2: %s\n", argv[2]);
for (int i = 1; i <= argc + 1; i++) {
if (strcmp("-i", argv[i]) == 0) {
printf("%s\n", "found -i");
}
else{
printf("%s\n", "did not find -i");
}
}
只是尝试一个标志(-i
),但我希望它同时读取一个或多个标志并调用相应的函数。
当我执行程序时:
./program-name test -i
Argv 0: test
Argv 1: -i
Argv 2: (null)
found -i
Segmentation fault
为了简化,argc
是命令行参数的个数,参数保存在argv[]
中。由于 C 数组具有基于 0
的索引,因此在您的代码中,您需要更改
for (int i = 1; i <= argc + 1; i++)
到
for (int i = 1; i < argc; i++)
限制对有效参数列表的访问。
要对此添加一点参考,引用 C11
,第 §5.1.2.2.1 章,程序启动(强调我的)
If the value of
argc
is greater than zero, the string pointed to byargv[0]
represents the program name;argv[0][0]
shall be the null character if the program name is not available from the host environment. If the value ofargc
is greater than one, the strings pointed to byargv[1]
throughargv[argc-1]
represent the program parameters.
您超出了 argv
的界限; for
循环的条件不正确。应该是 i < argc
.
另外,为什么要重新发明轮子?查看 getopt()
.
不要重做已证明可靠的旧代码。它浪费时间并重复工作。作为一个长期的 C 编码器,我总是(当我记得时)在尝试从头开始之前先查看代码库。我先重新调整用途然后创建。我很聪明,知道在我之前有很多更聪明的编码员。
使用免费且有效的 getopt() 和 getopt_long() 函数为您解析命令行参数。如果您 google 搜索 "getopt example" but here is the GNU C tutorial.
,代码库中有很多示例#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main (int argc, char **argv)
{
int aflag = 0;
int bflag = 0;
char *cvalue = NULL;
int index;
int c;
opterr = 0;
while ((c = getopt (argc, argv, "abc:")) != -1)
switch (c)
{
case 'a':
aflag = 1;
break;
case 'b':
bflag = 1;
break;
case 'c':
cvalue = optarg;
break;
case '?':
if (optopt == 'c')
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
else if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf (stderr,
"Unknown option character `\x%x'.\n",
optopt);
return 1;
default:
abort ();
}
printf ("aflag = %d, bflag = %d, cvalue = %s\n",
aflag, bflag, cvalue);
for (index = optind; index < argc; index++)
printf ("Non-option argument %s\n", argv[index]);
return 0;
}
用你的代码和你的循环,这一行是错误的:
(strcmp("-i", argv[i])
当你将argv[i]传递给strcmp时,你应该确保argv[i]不为NULL。该函数以 NULL 指针作为参数会发生段错误。您应该更好地测试 argv[i] != NULL 或将 i <= argc 放在循环中而不是 i <= argc + 1 ,后者在 argv 字符串数组中包含 NULL 指针。