-3

I seem to be unable to understand why do these two cases behave differently:

const char* TEXT = "hello world!";
int length = (int) strlen(TEXT);
char* array[length];

this is ok, however this one:

char* text;
scanf("%[^\n]s", text);
// input "hello world!" and press enter
int length = (int) strlen(text);
char* array[length];

ends with a segmentation fault

what am I missing?

hvertous
  • 1,133
  • 11
  • 25
  • 3
    You have not allocated space for the second string, so you're trying to put the input, well, God knows where. – Federico klez Culloca Oct 28 '19 at 12:09
  • 2
    In the second example you have a pointer `text`, but *where does it point?* – Some programmer dude Oct 28 '19 at 12:09
  • 1
    In your second case, your have declared `text` as a pointer, but haven't pointed it at anything. You need to define a memory buffer (character array) somewhere and point `text` to it. – Adrian Mole Oct 28 '19 at 12:09
  • 2
    On an unrelated note, the format `%[^\n]s` is most likely wrong. It reads a line and then the `scanf` function expects a literal `s` in the input. I guess you want only `%[^\n]`. – Some programmer dude Oct 28 '19 at 12:11
  • 1
    Why are you casting the result from `strlen` instead of declaring `length` as an `size_t`? – klutt Oct 28 '19 at 12:20
  • FYI, `char *array[length];` does not define a pointer to an array that can hold `length` characters. It defines an array of pointers, none of which have been initialized to point to anything. It is likely not what you want unless the subsequent processing involves using one string for each character in the input. – Eric Postpischil Oct 28 '19 at 12:21

1 Answers1

3

For the scanf call, text parameter, you do not allocate any memory. You also do not initialize the variable to a value. This results in scanf writing to random memory, which causes your segmentation fault.

To fix this issue you need to allocate a buffer of a reasonable size:

char* text = malloc(1024);

1024 is the maximum size that you expect the input data to be. This, however, still leaves the code vulnerable to buffer overflows. To prevent buffer overflows you can inform scanf that text is of a certain size; look for the answers here

If you do not want to allocate the memory yourself, scanf can do it for you:


Note that the POSIX 2008 (2013) version of the scanf() family of functions supports a format modifier m (an assignment-allocation character) for string inputs (%s, %c, %[). Instead of taking a char * argument, it takes a char ** argument, and it allocates the necessary space for the value it reads:

char *buffer = 0;
if (sscanf(data, "%ms", &buffer) == 1)
{
    printf("String is: <<%s>>\n", buffer);
    free(buffer);
}

If the sscanf() function fails to satisfy all the conversion specifications, then all the memory it allocated for %ms-like conversions is freed before the function returns.

Gizmo
  • 1,990
  • 1
  • 24
  • 50