在 c 中使用指针获取字符串输入使我在一个函数中出现分段错误。相同的代码块适用于另一个功能?

Taking string input using pointers in c gives me segmentation fault in one function. Same block of code works fine for another function?

所以我想使用 char* 指针将名称输入作为字符串。 我在网上查看并找到了一个解决方案,方法是使用 malloc 为我的指针提供内存,然后使用 scanf 获取输入,如下所示:

  char *userInput = (char*)malloc(20 * sizeof(char));
  printf("\nEnter a name: ");
  scanf("%s",userInput);
  char *name = (char*)malloc(getLength(userInput)* sizeof(char));
  name = userInput;
  if(name == NULL){
    printf("Memory not allocated");
    exit(0);
  }
  free(userInput);

这有效,所以我将其复制并粘贴到另一个需要类似输入的函数,如下所示:

  char *userInput = (char*)malloc(20 * sizeof(char));
  printf("\nEnter a name: ");
  scanf("%s",userInput);
  char *searched = (char*)malloc(getLength(searched)* sizeof(char));
  searched = userInput;
  if(searched == NULL){
    printf("Memory not allocated");
    exit(0);
  }
  free(userInput);

但是当我 运行 这个函数的代码时,它给了我 "exited, segmentation fault"。

关于为什么它在我的第二个函数中不起作用的任何想法?

编辑:getLength() 是一个 returns 给定字符串长度的函数。

你在网上找到的代码,如果你复制正确,是错误的。问题是您正在释放 userInput,即使 searched 指向该内存。

您应该在释放之前将字符串从 userInput 复制到 searched

但是 userInput 不需要使用动态分配。您可以只使用本地数组。

分配searched时应使用userInput的长度。并且您需要加 1 以便为空终止符留出空间。

在尝试复制userInput之前,您应该检查分配是否成功。

  char userInput[20];
  printf("\nEnter a name: ");
  scanf("%19s",userInput); // limit input length to 19 so it fits in userInput
  char *searched = malloc((strlen(userInput)+1)* sizeof(char));
  if(searched == NULL){
    printf("Memory not allocated");
    exit(0);
  }
  strcpy(searched, userInput);

这两个代码块在这里不同:

char *name = (char*)malloc(getLength(userInput)* sizeof(char));
      ^^^^                           ^^^^^^^^^

char *searched = (char*)malloc(getLength(searched)* sizeof(char));
      ^^^^^^^^                           ^^^^^^^^^

第二个使用 searched 两次。所以你不同的正确修改原始代码。

但是,注意两个代码块都是错误的。

代码有几个问题(两个示例)。

scanf("%s",userInput); 真的很糟糕,因为它会让用户溢出你的缓冲区。看看 fgets 或者至少做 scanf("%19s",userInput);

这里:

char *name = (char*)malloc(getLength(userInput)* sizeof(char));
name = userInput;

malloc 行没用,因为您紧接着用 userInput 覆盖了 name。所以 malloc 给你的只是内存泄漏。

这里

free(userInput);

您释放 userInput 指向的内存。但是,由于您 name = userInput; 也是 name 指向的内存。所以释放后,none个指针是有效的。

我的猜测是,而不是:

name = userInput;

你会想要

strcpy(name, userInput);

就是说 - 我不知道 getLength 是什么,但也许 malloc 应该是:

char *name = (char*)malloc(1 + getLength(userInput)* sizeof(char));
                           ^^^

为字符串终止获取内存。至少那是你在使用 strlen

时所做的

所以:

  char *userInput = malloc(20);
  if(userInput == NULL){
    printf("Memory not allocated");
    exit(0);
  }

  printf("\nEnter a name: \n");
  scanf("%19s",userInput);

  char *searched = malloc(1 + strlen(userInput ));
  if(searched == NULL){
    printf("Memory not allocated");
    exit(0);
  }

  strcpy(searched, userInput);
  free(userInput);

但是...代码的真正目的是什么?

似乎 searched 应该保存(在动态分配的内存中)用户输入的字符串 并且 动态分配的内存量应该是需要保持字符串。

这在某些应用程序中可能有意义,但在您的情况下则不然!

第一个 malloc 是 20 个字符。因此,第二个 malloc 将用于 20 个或更少的字符。

由于 malloc 有内存开销和一些对齐要求,例如malloc(20) 超过 20 个字节。换句话说 - malloc(20)malloc(10) 使用的 实际内存 的差异可能很小。所以代码的整个想法是非常无用的——你不会通过执行第二个 malloc 和字符串复制来节省大量内存。

所以你应该简单地做:

  char *searched = malloc(20);
  if(searched == NULL){
    printf("Memory not allocated");
    exit(0);
  }

  printf("\nEnter a name: \n");
  scanf("%19s",searched);

  // Go on using searched
  ...
  ...


  // Somewhere later in the code, call free
  free(searched);

只有当您的程序输入的字符串有时很长有时又很短时,原始代码才有意义。在那种情况下,第一个 malloc 将用于更大的数字,例如1000000 个字符,然后将输入复制到较小的缓冲区才有意义。