更改 argv 后的 C 分段错误
C segmentation fault after altering argv
我想在 C 中更改 argv
的值,但遇到了分段错误。这是代码。
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
for (int i = 1; argv[i]; i++)
{
char *val;
printf("before: %d %s\n", i, argv[i]);
argv[i] = "bar=foo";
printf("after: %d %s\n", i, argv[i]);
char *arg = argv[i];
val = strchr(arg, '=');
*val = '[=10=]';
}
return 0;
}
我正在传递参数 foo=bar
(并尝试在第 11 行将其更改为 bar=foo
)。输出如下所示:
before: 1 foo=bar
after: 1 bar=foo
因此,修改实际上发生了,但是行 *val = '[=15=]';
导致了分段错误。
谁能告诉我为什么会这样,我该如何预防?
您正在此处写入字符串文字
val = strchr(arg, '=');
*val = '[=10=]';
字符串文字存在于程序的只读段中,尝试更改它们会引发未定义的行为。
这一行之后
argv[i] = "bar=foo";
argv[i]
指向字符串文字 "bar=foo"
然后,创建一个指向 argv[i]
的新指针 arg
最后 val
指向arg
中的 =
然后你去尝试用 nul
.
覆盖
您使 argv[i]
指向一个 字符串文字 ,这是一个 只读 字符数组。然后您尝试修改此只读数组,导致 未定义的行为。
您应该对字符串文字使用 const char *
是有原因的。
有几种方法可以解决您的问题。第一个也是最简单的,特别是如果您要对所有参数使用相同的字符串(不太可能,除非在人为的示例中,例如您展示的示例)是使用数组,如 char argument[] = "bar=foo";
。依靠数组自然衰减到指向其第一个参数的指针,您可以在对 argv[i]
的赋值中使用它,并将数组修改为您满意的内容。
但就像我说的那样,除了简单的示例外,它不会真的很有用。这给我们留下了另一种选择,例如使用strdup
动态分配和复制字符串(或者,如果 strdup
不可用,它不是标准函数,您可以手动使用 malloc
和 strcpy
)。由于您已经动态分配了内存,因此也可以根据自己的喜好对其进行修改。这里的问题是您需要跟踪原始指针并使用 free
再次释放它们。
所以这些基本上是您可以使用的两种解决方案 use.One 是不现实的,而另一种具有动态内存分配和所有随之而来的问题。对于您的问题,确实没有好的,尤其是没有 简单 的解决方案。
我想在 C 中更改 argv
的值,但遇到了分段错误。这是代码。
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
for (int i = 1; argv[i]; i++)
{
char *val;
printf("before: %d %s\n", i, argv[i]);
argv[i] = "bar=foo";
printf("after: %d %s\n", i, argv[i]);
char *arg = argv[i];
val = strchr(arg, '=');
*val = '[=10=]';
}
return 0;
}
我正在传递参数 foo=bar
(并尝试在第 11 行将其更改为 bar=foo
)。输出如下所示:
before: 1 foo=bar
after: 1 bar=foo
因此,修改实际上发生了,但是行 *val = '[=15=]';
导致了分段错误。
谁能告诉我为什么会这样,我该如何预防?
您正在此处写入字符串文字
val = strchr(arg, '=');
*val = '[=10=]';
字符串文字存在于程序的只读段中,尝试更改它们会引发未定义的行为。
这一行之后
argv[i] = "bar=foo";
argv[i]
指向字符串文字 "bar=foo"
然后,创建一个指向 argv[i]
的新指针 arg
最后 val
指向arg
中的 =
然后你去尝试用 nul
.
您使 argv[i]
指向一个 字符串文字 ,这是一个 只读 字符数组。然后您尝试修改此只读数组,导致 未定义的行为。
您应该对字符串文字使用 const char *
是有原因的。
有几种方法可以解决您的问题。第一个也是最简单的,特别是如果您要对所有参数使用相同的字符串(不太可能,除非在人为的示例中,例如您展示的示例)是使用数组,如 char argument[] = "bar=foo";
。依靠数组自然衰减到指向其第一个参数的指针,您可以在对 argv[i]
的赋值中使用它,并将数组修改为您满意的内容。
但就像我说的那样,除了简单的示例外,它不会真的很有用。这给我们留下了另一种选择,例如使用strdup
动态分配和复制字符串(或者,如果 strdup
不可用,它不是标准函数,您可以手动使用 malloc
和 strcpy
)。由于您已经动态分配了内存,因此也可以根据自己的喜好对其进行修改。这里的问题是您需要跟踪原始指针并使用 free
再次释放它们。
所以这些基本上是您可以使用的两种解决方案 use.One 是不现实的,而另一种具有动态内存分配和所有随之而来的问题。对于您的问题,确实没有好的,尤其是没有 简单 的解决方案。