简体   繁体   English

使用 c 中的指针进行字符串输入会给我一个 function 中的分段错误。 相同的代码块适用于另一个 function?

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

So I want to take inputs of names as strings using char* pointers.所以我想使用 char* 指针将名称输入作为字符串。 I looked online and found a solution by giving my pointer memory using malloc and then taking the input using scanf , as shown below:我在网上查看并找到了一个解决方案,方法是使用 malloc 给我的指针 memory 然后使用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);

This works, so I copied and pasted it to another function where similar input is required as below:这行得通,所以我将它复制并粘贴到另一个需要类似输入的 function 中:

  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);

But when I run the code for this function, it gives me "exited, segmentation fault".但是当我运行这个 function 的代码时,它给了我“退出,分段错误”。

Any ideas on why it doesn't work in my second function?关于为什么它在我的第二个 function 中不起作用的任何想法?

EDIT: getLength() is a function that returns the length of a given string.编辑: getLength() 是一个 function ,它返回给定字符串的长度。

The code you found online, if you reproduced it correctly, is wrong.您在网上找到的代码,如果您正确地复制它,是错误的。 The problem is that you're freeing userInput , even though searched points to that memory.问题是您正在释放userInput ,即使searched指向 memory。

You should copy the string from userInput to searched before freeing it.您应该在释放它之前将字符串从userInput复制到searched

But there's no need to use dynamic allocation for userInput .但是没有必要对userInput使用动态分配。 You can just use a local array.您可以只使用本地数组。

You should use the length of userInput when allocating searched .分配searched时应该使用userInput的长度。 And you need to add 1 to allow room for the null terminator.并且您需要加 1 为 null 终结器留出空间。

You should check whether the allocation was successful before trying to copy userInput into it.在尝试将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);

The two code blocks differs here:这两个代码块在这里有所不同:

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

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

The second uses searched twice.第二种用途searched了两次。 So you different modify the original code correctly.因此,您可以正确修改原始代码。

However, notice that both code blocks are wrong.但是,请注意两个代码块都是错误的。

There are several problems with the code (both examples).代码有几个问题(两个例子)。

scanf("%s",userInput); is real bad as it let the user overflow your buffer.真的很糟糕,因为它让用户溢出你的缓冲区。 Look at fgets instead or at least do scanf("%19s",userInput);看看fgets或者至少做scanf("%19s",userInput);

Here:这里:

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

the malloc line is useless as you overwrite name with userInput immediately after. malloc行是无用的,因为您之后立即用userInput覆盖name So all malloc gives you is a memory leak.所以所有malloc给你的是 memory 泄漏。

And here和这里

free(userInput);

you free the memory that userInput points to.您释放userInput指向的 memory。 However, since you did name = userInput;但是,既然你做了name = userInput; it is also the memory that name points to. name指向的也是memory。 So after the free, none of the pointers are valid.所以在free之后,没有一个指针是有效的。

My guess is that instead of:我的猜测是,而不是:

name = userInput;

you would want你会想要

strcpy(name, userInput);

That said - I'm don't know what getLength is but maybe the malloc should be:也就是说 - 我不知道getLength是什么,但也许malloc应该是:

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

to get memory for the string termination.获取 memory 用于字符串终止。 At least that is what you do when using strlen至少这是你在使用strlen时所做的

So:所以:

  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);

But... what is the real purpose of the code?但是......代码的真正目的是什么?

It seems to be that searched shall hold (in dynamic allocated memory) a string entered by the user and that the amount dynamic allocated memory shall be exactly what is required to hold the string.似乎searched应该保存(在动态分配的内存中)用户输入的字符串,并且动态分配的 memory 的数量应该正是保存字符串所需的量。

That could make sense in some application but not in your case!这在某些应用程序中可能有意义,但在您的情况下则不然!

The first malloc is for 20 chars.第一个malloc用于 20 个字符。 Consequently, the second malloc will be for 20 or less chars.因此,第二个malloc将用于 20 个或更少的字符。

Since malloc has a memory overhead and some alignment requirement, the amount of real memory required by, eg malloc(20) is more than 20 bytes. Since malloc has a memory overhead and some alignment requirement, the amount of real memory required by, eg malloc(20) is more than 20 bytes. In other words - the difference in real memory used by malloc(20) and malloc(10) is likely to be small.换句话说 - malloc(20)malloc(10)使用的实际 memory的差异可能很小。 So the whole idea of the code is pretty useless - you don't save significant memory by doing the second malloc and the string copy.所以代码的整个想法是非常无用的 - 你不会通过执行第二个malloc和字符串复制来节省大量的 memory 。

So you should simply do:所以你应该简单地做:

  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);

The original code only makes sense if your program sometimes gets very long strings as input and sometimes very short.仅当您的程序有时将很长的字符串作为输入并且有时很短时,原始代码才有意义。 In that case the first malloc would be for a much bigger number, eg 1000000 chars, and then it would make sense to copy the input to a smaller buffer afterwards.在这种情况下,第一个malloc将用于更大的数字,例如 1000000 个字符,然后将输入复制到更小的缓冲区是有意义的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM