Thread: Going out of Array bounds and how it affects input and output

  1. #1
    Registered User Vespasian's Avatar
    Join Date
    Aug 2011
    Posts
    181

    Going out of Array bounds and how it affects input and output

    Hey guys.

    I tried experimenting with deliberately putting in more elements than an array has and printing out the results. The reason im doing this is basically in anticipation that should the user do something wrong, I want to understand how to handle these scenarios.

    I write this code:

    Code:
    #include <stdio.h>
    
    int main(void)
    {
        int a[5], b, c;
        for (b=0; b< 10&&(scanf("%d", &c)); b++)
        a[b]=c;
        for(b=0;b<15;b++)
        printf("%d ", a[b]);
    return 0;
    }
    So if you input, say:
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10
    It prints out:
    1, 2, 3, 4, 5, 10, 7, 8, 9, 10, a large number, another large number, etc until the fifteenth last element which, interestingly, contains a 1
    Q's:
    1) I am printing out elements of an array that dont really exist (>5), and yet, it still prints out the same numbers I put in input. Is this because, somehow, all your inputs are "contiguous" next to the defined array?
    2) If so, how come the last input (10) replaces 6 in the start of the numbers that go out of array bounds?

    I guess its a silly non trivial attempt to understand the deeper workings of C

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Vespasian
    I tried experimenting with deliberately putting in more elements than an array has and printing out the results.
    You deliberately played with undefined behaviour.

    Quote Originally Posted by Vespasian
    The reason im doing this is basically in anticipation that should the user do something wrong, I want to understand how to handle these scenarios.
    The correct way to handle this scenario is to ensure that the array is never accessed out of bounds.

    Quote Originally Posted by Vespasian
    1) I am printing out elements of an array that dont really exist (>5), and yet, it still prints out the same numbers I put in input. Is this because, somehow, all your inputs are "contiguous" next to the defined array?
    More likely you merely wrote to memory next to that allocated to you, and by luck it worked.

    Quote Originally Posted by Vespasian
    2) If so, how come the last input (10) replaces 6 in the start of the numbers that go out of array bounds?
    Maybe the space allocated for c happened to get written to when you went beyond the bounds of the array.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Is this because, somehow, all your inputs are "contiguous" next to the defined array?
    Yes, and you can easily confirm this by also printing the memory address.

    Code:
    for(b=0;b<15;b++)
         printf("%d %p ", a[b], a+b);

  4. #4
    Registered User Vespasian's Avatar
    Join Date
    Aug 2011
    Posts
    181
    By the way, I see this forum finally decided to add line numbering and colouring to code tags! about time!

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by Vespasian View Post
    I tried experimenting with deliberately putting in more elements than an array has and printing out the results. The reason im doing this is basically in anticipation that should the user do something wrong, I want to understand how to handle these scenarios.
    Why on earth would you do that. That is not the solution. The solution is to write code such that if the user types in extra stuff, it just gets thrown away, not stuffed into memory you don't own.

    1) I am printing out elements of an array that dont really exist (>5), and yet, it still prints out the same numbers I put in input. Is this because, somehow, all your inputs are "contiguous" next to the defined array?
    You're stepping into in undefined behavior. It may do something that you expect, it may not. Just don't do it, since it's not reliable. As for why it works for indexes 5-9, but not 10-14, you only allow the user to write 10 thing into your array (b<10 in your first loop), so indexes 0-9 are full of user input. Indexes 10-14 are full of garbage, some large numbers and a 1. Again, you don't own a[5] through a[14], so you can't assume anything about the values therein. You also can't guarantee that all variables are contiguous, or in the order defined. That's up to the whim of the compiler writers and the architecture's alignment requirements. Maybe you got away with writing to them this time. Maybe not next time. Bad juju all over the place. Don't even try to understand it.

    2) If so, how come the last input (10) replaces 6 in the start of the numbers that go out of array bounds?
    Most likely because you scanf into c, which probably happens to be located at where the compiler thinks a[6] is. Don't worry though, it's undefined behavior.

    I guess its a silly non trivial attempt to understand the deeper workings of C
    Silly, yes, but also trivial. You're trying to define undefined behavior, which doesn't work. Don't do it.
    Last edited by anduril462; 09-20-2011 at 10:50 AM.

  6. #6
    Registered User Vespasian's Avatar
    Join Date
    Aug 2011
    Posts
    181
    I agree with you all that it must be prevented in the first place.

    But I was told on this forum that for variable length user input, say a string, a "sufficiently large" array must be made or I think it was termed large enough "buffer" (same thing?). So thats when I wondered what if it goes over this...

  7. #7
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Quote Originally Posted by Vespasian View Post
    I agree with you all that it must be prevented in the first place.

    But I was told on this forum that for variable length user input, say a string, a "sufficiently large" array must be made or I think it was termed large enough "buffer" (same thing?). So thats when I wondered what if it goes over this...
    You need to make sure it doesn't. That is why fgets() is recomended over gets() for example, since you can set the maximum amount of characters that will be accepted. Or in case of scanf use a length in addition to the %s format specifier.

  8. #8
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Vespasian View Post
    1) I am printing out elements of an array that dont really exist (>5), and yet, it still prints out the same numbers I put in input. Is this because, somehow, all your inputs are "contiguous" next to the defined array?
    Yes, as you increase the array index (even out of bounds) C works from a calculated offset from the array pointer, so they will end up being contiguous in memory... But that's not what you should be concerned about. You should be wondering what other variables or stack data you clobbered in the process.
    It worked this time as an act of pure dumb luck... don't count on it ever working again.

    2) If so, how come the last input (10) replaces 6 in the start of the numbers that go out of array bounds?
    It doesn't... i's probably that you are clobbering your C variable with out of bounds array content. If you put in different numbers... 100, 200, etc. you would probably also discover you've clobbered your loop counter (b).

    I guess its a silly non trivial attempt to understand the deeper workings of C
    What you've just discovered is one of the most important things you have to know about C ...

    C contains no runtime error checking whatsoever; it is entirely on your shoulders as a programmer to make sure stuff like this doesn't happen.

  9. #9
    Registered User Vespasian's Avatar
    Join Date
    Aug 2011
    Posts
    181
    Just to add...

    Not using gets function, there is no other way to deal with variable user input other than making a "sufficiently large" array. I understand that accessing the array out of bounds must not be done, but what about simply overfilling the array by itself, is that a bad thing? Or the programme will simply ignore the overfilled elements in an array and wont cause any side effects down the line...

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Regardless of how large "sufficiently large" is, it is worth checking to see if the buffer returned by fgets() contains a \n (or not). If it doesn't, then your buffer wasn't large enough, so you should malloc some temporary storage, copy the line fragment to the temp and keep doing that until you do find a \n in your input.

    There are of course several different ways of storing the fragments whilst waiting for the \n to show up.

    BUFSIZ is almost certainly "large enough" for anything the user might be typing in.

    However, if you're parsing the output of say the pre-processor (where multi-line macros are expanded onto a single line), or certain XML files, then you might need to deal with the exceptional cases.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by Vespasian View Post
    So thats when I wondered what if it goes over this...
    If it goes over, you've programmed it wrong.


    Quzah.
    Hope is the first step on the road to disappointment.

  12. #12
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    In most cases, there's no such thing as a sufficiently large array in the context of preventing a buffer overrun. You either make it so that the array absolutely cannot be be overflowed, or your have a buffer overrun bug. That's the kind of bug that often allows baddies to execute arbitrary code of their choosing on your system and potentially take control of it.

    You cannot take the "ambulance at the bottom of a cliff" approach when it comes to buffer overruns.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  13. #13
    Registered User Vespasian's Avatar
    Join Date
    Aug 2011
    Posts
    181
    Quote Originally Posted by Subsonics View Post
    You need to make sure it doesn't. That is why fgets() is recomended over gets() for example, since you can set the maximum amount of characters that will be accepted. Or in case of scanf use a length in addition to the %s format specifier.
    Okay I took this advice. So my following code is safe? BUT it cant allocate extra memory should input exceed BUFFERSIZE. So if this is correct my next step is to do what Salem says and malloc some extra chunks. Ill do this next, tell me what you think!

    Code:
    #include <stdio.h>
    #define BUFFERSIZE 10
    
    char buffer[BUFFERSIZE];
    
    void getinput()
    {
        fgets(buffer, BUFFERSIZE, stdin);
    }
    
    int main ()
    {
        int n;
        getinput();
        printf("%s", buffer);
        return 0;
    }

  14. #14
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Looks like you understand it.

    I think of it like a soldier - one step out of the array bounds, and I'm stepping into the mine field. Will I step on a mine? Who knows? Maybe a bunch of goats have grazed there, and already set off every land mine, already. Maybe the map is wrong, and there are no land mines here. Maybe there's one waiting for my very first step into the mine field.

    You just can't tell.

    If you want to be safe - stay out of the mine field.

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Well aside from the use of global variables, it would look something like this.
    Code:
    char buff[BUFFERSIZE];
    while ( fgets( buff, BUFFERSIZE, stdin) != NULL ) {
        char *t = malloc( strlen(buff) + 1 );  // + check errors
        strcpy( t, buff );
        // store t somewhere, say an array of pointers, or linked list
        if ( buff[strlen(buff)-1] == '\n' ) break;
    }
    // do something with your very long line spread through your
    // saved data structure of t pointers.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Input and output problem with 2D array
    By Roy01 in forum C++ Programming
    Replies: 8
    Last Post: 10-22-2006, 08:16 AM
  2. array bounds checking
    By anykey in forum C++ Programming
    Replies: 2
    Last Post: 08-19-2005, 04:13 PM
  3. array input/output problem
    By glowstick in forum C Programming
    Replies: 1
    Last Post: 09-10-2002, 07:56 PM
  4. FILE input/output and ARRAY
    By poorman in forum C Programming
    Replies: 1
    Last Post: 03-05-2002, 04:17 PM