0

Below is the function which returns a character pointer to a string which was initialized using getc(stdin)- character by character.

  1. Is there any flaw in memory allocation method? Is this an efficient way when we don't know the size of the string which is going to be entered, if not please explain.

  2. Using getc(stdin) --will it lead to buffer overflow???()

  3. If I must not use getc(stdin), what will help me achieve my goal in a more efficient way?

Code so far:

char *getstring()
{
  char *str = NULL, *tmp = NULL;
  int size = 0, index = 0;
  int ch = -1;
  int length=0;
  while (ch!=0) 
  {
    ch = getc(stdin);

    if (ch == '\n')
    {   
        ch = 0;
    }

    if (size <= index) 
    {
        size += 15;
        tmp = (char*)realloc(str, size);
        if (!tmp) 
        {
            free(str);
            str = NULL;    
        }
        str = tmp;
    }
    str[index++] = ch;
  }

  if(size==index)
  {
    return str;
  }
  else if(index<size)
  {
    length=strlen(str);
    tmp = (char*)realloc(str,(length+1));
    str[index]='\0';
    //cout<<"length:"<<length;
    str=tmp;
  }

  return str;
}
4
  • What is the variable ch? Commented May 26, 2015 at 15:45
  • It is an integer, getc returns an integer Commented May 26, 2015 at 15:48
  • Your code does not handle EOF. Commented May 26, 2015 at 15:50
  • 1
    str is NULL if realloc fails, str[index++] = ch; => NULL[index++] = ch; Commented May 26, 2015 at 15:52

2 Answers 2

1

Don't re-invent the wheel: use getline(3).

Example (from same URL):

   #define _GNU_SOURCE
   #include <stdio.h>
   #include <stdlib.h>

   int
   main(void)
   {
       FILE *stream;
       char *line = NULL;
       size_t len = 0;
       ssize_t read;

       stream = fopen("/etc/motd", "r");
       if (stream == NULL)
           exit(EXIT_FAILURE);

       while ((read = getline(&line, &len, stream)) != -1) {
           printf("Retrieved line of length %zu :\n", read);
           printf("%s", line);
       }

       free(line);
       fclose(stream);
       exit(EXIT_SUCCESS);
   }
Sign up to request clarification or add additional context in comments.

5 Comments

might want to fix the int main line. :)
Note that POSIX systems should not require _GNU_SOURCE to provide access to getline(). You might need to set #define _XOPEN_SOURCE 700 or #define _POSIX_C_SOURCE 200809L before the first header is included to see the declaration of getline(), though.
@MartinTörnwall it's on two lines. not a big deal
@user3711622 For declarations with a lot of tokens before the actual function name, or complex return types, it can be nice to put the function name on a new line - makes it easier to spot when looking through a large body of code. That said, I did not write said example.
That, and you can regexp-search for ^<function name>. While I've rarely seen it in other languages, this is a very common formatting pattern in C.
0

"Is there any flaw in memory allocation method?" Yes, when the reallocation fails, you free the previous memory pointer, assign NULL to it, then overwrite it with tmp, which has the value NULL, and then plough on using a NULL pointer.

if (size <= index) 
{
    size += 15;
    tmp = (char*)realloc(str, size);
    if (!tmp)                   // <--- NULL!
    {
        free(str);
        str = NULL;    
    }
    str = tmp;                  // <--- NULL!
}
str[index++] = ch;              // <--- NULL!

But if realloc fails you have little choice but to abandon the task in hand gracefully.

Also if you allow for the 0-terminator at the same time, you'll save several messy lines of code and another reallocation. And you don't always insert the '\0'.

if (size <= index+1)            // allow room for string terminator

1 Comment

@BLUEPIXY only just noticed your comment.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.