在C语言中使用指针接收字符串输入时,我在一个函数中出现了分段错误。同样的代码块在另一个函数中工作正常?

问题描述 投票:0回答:1

所以我想用char*指针把输入的名字作为字符串,我在网上找了一个解决办法,用malloc给我的指针内存,然后用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".

有什么想法,为什么在我的第二个函数中不能工作?

EDIT:getLength()是一个返回给定字符串长度的函数。

c string pointers segmentation-fault malloc
1个回答
1
投票

两个代码块在这里有所不同。

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 行是无用的,因为你覆盖了 nameuserInput 紧接着。所以所有 malloc 给你的是一个内存泄漏。

而这里

free(userInput);

你释放的内存 userInput 指的是。然而,既然你做了 name = userInput;也是 记忆 name 指向。所以,免费之后,所有的指向都是无效的。

我的猜测是,与其用:

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字符,然后将输入复制到一个较小的缓冲区是有意义的。


1
投票

你在网上找到的代码,如果你照搬正确的话,是错误的。问题是你在释放 userInput纵然 searched 指向该内存。

你应该把字符串从 userInputsearched 前释放它。

但没有必要对以下情况使用动态分配。userInput. 你可以直接使用一个本地数组。

你应该使用 userInput 当分配 searched. 而且你需要添加1来为null终止符留出空间。

在尝试复制之前,你应该检查分配是否成功。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);
© www.soinside.com 2019 - 2024. All rights reserved.