【问题标题】:Segmentation fault when writing to array of strings写入字符串数组时出现分段错误
【发布时间】:2020-01-25 05:55:46
【问题描述】:

我正在尝试将 argv 中传递的一些参数复制到字符串数组中。这是我的程序。

#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int main (int argc, char * argv[]) {
    char **args = malloc(argc * sizeof(char *));
    for (int i = 0; i < argc - 1; ++i) {
        strcpy(*(args+i), argv[i+1]);
    }
}

我在 for 循环中遇到分段错误。为什么会这样?

【问题讨论】:

  • 您只是在分配一个指针数组。您还需要分配数组中的每个项目。

标签: c segmentation-fault


【解决方案1】:

你得到了分段错误,因为你使用了未初始化的指针。

换句话说:*(args+i) 未初始化。

让我们看看你的记忆:

char **args = malloc(argc * sizeof(char *));

这将给出一个局部变量args,它指向一个由argc 指向char 的指针组成的动态分配内存区域。看起来像这样:

但指向 char 的 argc 指针未初始化(即 malloc 未初始化任何内容)所以真实情况是:

也就是说,argc 指向 char 的指针可以指向任何地方。

所以当你这样做时

strcpy(*(args+i), argv[i+1]);
       ^^^^^^^^^
       Read uninitialized pointer

您读取第 i 个未初始化的指针并将 argv[i+1] 处的字符串复制到该位置。换句话说 - 到一个我们不知道在哪里并且最喜欢不属于您的程序的位置。这可能会导致段错误。

因此,在您复制任何内容之前,您希望这些字符指针指向某些字符。喜欢:

所以基本上你需要做额外的malloc

现在一个问题是:malloc 需要多少个字符?

嗯,只有知道输入字符串的长度才能知道。因此,您需要将 malloc 放入循环中。喜欢:

int main (int argc, char * argv[]) {
    char **args = malloc(argc * sizeof(char *));
    for (int i = 0; i < argc - 1; ++i) {
        *(args+i) = malloc(strlen(argv[i+1]) + 1);  // Allocate memory
        strcpy(*(args+i), argv[i+1]);
    }
}

注意:

  • 你不需要写sizeof(char),因为它总是1

  • 您必须将输入字符串的字符串长度加 1,以便为字符串终止保留内存。

  • 您应该始终检查malloc 不返回NULL

  • 您可以使用更易读的形式args[i],而不是*(args+i)

所以在真正执行之后,图片可能是:

【讨论】:

    【解决方案2】:

    问题在于您的这部分代码:

    malloc(argc * sizeof(char *));
    

    不要认为sizeof(char*) 会给你字符串的大小。

    What is the size of a pointer?

    解决方案:

    int main(int argc, char* argv[])
    
    {
        char* copyOfArgv;
    
        copyOfArgv = strdup(argv[1]);
    }
    

    strdup() - what does it do in C?

    【讨论】:

      【解决方案3】:

      问题是您为指针分配了内存,而不是为字符串(来自argv 本身的参数),因此strcpy 无效 - 导致segmentation fault

      最好是:

      为指针分配内存(就像您所做的那样),然后使这些指针指向传递的参数。示例:

       #include <string.h>
       #include <stdlib.h>
       #include <unistd.h>
      
       int main (int argc, char * argv[]) {
           char **args = malloc(argc*sizeof(char *)); //allocated memory for the pointers only
           int i=0;
      
           for(;i<argc;i++)
           {
               args[i]=argv[i];  //making the pointers POINT to the arguments including the 0th argument as well
               i++;
           }
           return 0;
       }
      

      对于使用strcpy,您应该为参数本身分配内存,然后复制它们。

      【讨论】:

      • 虽然这在代码方面是正确的,但我不明白这一点。如果程序不需要字符串的真实副本,为什么要复制指针?在这种情况下,程序可以简单地使用argv 而根本不复制任何内容。
      猜你喜欢
      • 2013-08-31
      • 2017-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多