更改 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 不可用,它不是标准函数,您可以手动使用 mallocstrcpy)。由于您已经动态分配了内存,因此也可以根据自己的喜好对其进行修改。这里的问题是您需要跟踪原始指针并使用 free 再次释放它们。

所以这些基本上是您可以使用的两种解决方案 use.One 是不现实的,而另一种具有动态内存分配和所有随之而来的问题。对于您的问题,确实没有好的,尤其是没有 简单 的解决方案。