0

Is there any way to handle error index out of bounds in C

i just want to to know, please explain it in context of this example. if i enter a string more than 20 char i get * stack smashing detected *: ./upper1 terminated Aborted (core dumped)

main()
{
char st[20];
int i;

 /* accept a string */
 printf("Enter a string : ");
 gets(st);

 /* display it in upper case */
 for ( i = 0 ; st[i] != '\0';  i++)
  if ( st[i] >= 'a'  &&  st[i] <= 'z' )
       putchar( st[i] - 32);
  else
       putchar( st[i]);
}

I want to handle those and stop them and display a custom message as done in Java's Exception Handling. Is it possible ? If yes how

Thanks in advance

Subramanyam M
  • 335
  • 2
  • 6
  • 18
  • 1
    `C` doesn't check array index out of bound. – Jayesh Bhoi Sep 14 '14 at 12:08
  • 2
    `gets()` has been deprecated in C11. It's always been dangerous anyway. Don't use it; use `fgets()` instead. And no, there's no way to handle out of bounds issue in Cother than programmatically ensuring it yourself. – P.P Sep 14 '14 at 12:10

3 Answers3

4

To answer the original question: there is no way to handle implicitly out-of-bound array indexes in C. You should add that check explicitly in your code or you should prove (or at least be absolutely sure) that it does not happen. Beware of buffer overflow and other undefined behavior, it can hurt a lot.

Remember that C arrays don't "know" their size at runtime. You should know and manage that size, especially when passing arrays (which become decayed into pointers). Read also about flexible array members in struct-s (like here).

BTW, your code is poor taste. First, the char st[20]; is really too small these days: an input line can have really a hundred of characters (I often have terminal emulators wider than 80 columns). So make it e.g.

 char st[128];

Then, as every one told you, gets(3) is dangerous, it is documented as "Never use this function". Take the habit of reading the documentation of every function that you dare use.

I would suggest to always clear such a string buffer with

memset (st, 0, sizeof st);

You should at the very least use fgets(3), but read the documentation first. You'll need to handle the failure case.

Also, your conversion to upper-case is specific to ASCII (and some other encodings). It won't work on old EBCDIC machine. And it is unreadable. So use isalpha(3) to detect letters (in ASCII or other single-byte encoding); but in UTF-8 it is more complex, since some letters -eg cyrillic ones- are encoded on several bytes). My family name (СТАРЫНКЕВИЧ when spelt in Russian) contains an Ы -which is a single letter called yery - whose UTF-8 encoding for the capital letter is 0xD0 0xAB on two bytes. You'll need an UTF-8 library like unistring to handle these. And use toupper(3) to convert (e.g. ASCII) letters to upper-case.

Notice that your main function is wrongly defined. It should return an int and preferably be declared as int main(int argc, char**argv).

At last, on Posix systems, the "right" way to read a line is to use the getline(3) function. It can read a line as wide as permitted by system resources (so it might read a line of a million characters on my machine). See this answer.

Regarding exceptions, C don't really have these (so most programmers take the habit to have functions giving some error code). However, for non-local jumps consider setjmp(3) to be used with great caution. (In C++, you have exceptions and they are related to destructors).

Don't forget to compile with all warnings and debug info (e.g. with gcc -Wall -g if using GCC). You absolutely need to learn how to use the debugger (e.g. gdb) and you also should use a memory leak detector like valgrind.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
3

Yes, you must use fgets() instead of gets(). In fact, gets() is officially deprecated and should never, ever be used, because it is impossible to use safely as you discovered.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
0

Though its not directly possible to detect that the user has written out of bounds it, we can add some logic to make sure to throw an error without crashing.

int main (int argc, char **argv)
{
   char user_input [USERINPUT_MAX];

    for (int i = 0; i < USERINPUT_MAX; ++i)
    {
        // read the character 
        // check for enter key, if enter break out of loop after adding null at end
        // if not enter,store it in array 
    }
    if (i == USERINPUT_MAX)
    {
        printf ("you have exceeded the character range");
    }
}

I guess you get the idea of how to handle such situations from user input.

Pradheep
  • 3,553
  • 1
  • 27
  • 35