-1

I'm stuck really badly on what could be causing this issue, and I really would like to understand what's happening behind the scenes for this to be occurring. The following code is meant to grab a string of max 99 character length, put it into a variable called word, and read the length; later on I am going to be reallocating the memory assigned to it by the amount of chars inside the string, but for now I just want to be able to get the input. Here's the code segment:

char* word = malloc(100);
printf("Enter a string:\n");
int x = scanf("%s", &word);
printf("Length = %d", x);
printf("Word is %s", word);

When used, this happens:

Enter a string:
123
1
Segmentation Fault

What's happening here? Why is this not working? I thought assigning memory with malloc would give it enough space, and then scanf would put my word into the variable? I need to use malloc because I need to realloc later to not use more memory than needed later.

Sourav Ghosh
  • 127,934
  • 16
  • 167
  • 234

4 Answers4

3

Looking at your snippet:

char* word = malloc(100);
printf("Enter a string:\n");
int x = scanf("%s", &word);

The problem is here in the last line I quoted. scanf() expects a pointer to some char array for %s. But using the address-of operator (&) takes the address of your pointer, so you're giving scanf() a pointer to your pointer word instead. This is undefined behavior, scanf() will just overwrite the pointer word (thereby destroying it) -- other strange stuff can happen. Simple solution: delete the &.

Still that's not all that's wrong with the code above, the following line:

int x = scanf("%s", word);

has undefined behavior as well. That's because you can never guarantee there will be a whitespace in the first 99 characters of input, so this code can overflow your buffer. Always use a field width for scanf() conversions to strings, here like this:

int x = scanf("%99s", word);

Finally, for a fixed and reasonably small amount of memory, there's really no need to dynamically allocate it (and I don't see you calling free() as would be required). Just replace the first line with

char word[100];

You can still write the rest of the code in the same way. The identifier of an array evaluates to a pointer to the first element in most contexts, e.g. when passing it to a function.

2

In your code

 int x = scanf("%s", &word);

should be changed to

 int x = scanf("%99s", word); //99 chars to be scanned - at max - see note below

as word is already a pointer to char, which

  • is the expected type of argument for %s
  • points to the memory you just allocated.

Quoting C11, chapter §7.21.6.2, for fscanf() family

s

[...] If no l length modifier is present, the corresponding argument shall be a pointer to the initial element of a character array large enough to accept the sequence and a terminating null character, which will be added automatically. [....]

Note: When in doubt / confusion, always check the data types.

  • word is of type char * - the correct and expected type
  • &word is of type char **. - type misatch

That said, couple of tips

  • always check for the successful execution/ return of library functions. (malloc(), scanf() etc) before using the result.
  • Always size-limit the scanning to prevent buffer overflow from overly long input.
Sourav Ghosh
  • 127,934
  • 16
  • 167
  • 234
  • Can you help me understand why this is needed; is it due to the way strings work in C (being arrays of chars) or? That makes sense actually, so if I've defined the variable as a pointer already, I don't need to use & in the scanf function? Neat! –  Jul 26 '18 at 09:41
  • @PixelRain Yeah, I think you got it, – Sourav Ghosh Jul 26 '18 at 09:43
  • @PixelRain you probably should read the chapter dealing with pointers in your C text book. – Jabberwocky Jul 26 '18 at 09:43
1

The problem lies here: int x = scanf("%s", &word);. Do not use the & with scanf blindly. It's true that you should pass the address to scanf but here you are passing the address of word. The variable word is an address in itself (or rather, contains an address). You want data to be written starting from that address.

Drop the &. Use int x = scanf("%s", word);

babon
  • 3,023
  • 1
  • 15
  • 18
0

Problem is with this statement int x = scanf("%s", &word). You have declared char* word = malloc(100) which means that it is a character array. You can modify the statement to int x = scanf("%s", word) (without &). Check the example code at https://www.tutorialspoint.com/c_standard_library/c_function_scanf.htm

Passing word itself provides the address to the first element of the array to store the values read.

Having said this if the amount of memory you need is already known at compile time it is better to statically allocate memory as:

char word[100]

To read a specified number of characters use the expression scanf("%<count>s", <stringVariable>. In your case it would be:

scanf("%99s", word)

Example code available here: https://en.wikipedia.org/wiki/Scanf_format_string

Shrikanth N
  • 602
  • 3
  • 15