Jump to content
  • Advertisement
Sign in to follow this  
Jaqen

Why is this working with arrays?

This topic is 3351 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I know accessing out of bounds is bad and will crash programs because I've written plenty of code in the past where it was crashing due to messing up boundaries in an array. However now I've run into a situation where it works fine. I wonder... is the compiler automatically adjusting the max size of the array?
#include <iostream>
using namespace std;

int main()
{
    int fn[5];
    fn[10] = 999;
    cout << fn[10] << endl;

    for(int i = 0; i < 10; i++)
    {
        fn = i;
        cout << fn << endl;
    }
}

Share this post


Link to post
Share on other sites
Advertisement
No, it's not. Writing over the end of an array is "undefined behaviour" which means anything can happen (including "works fine", even though it's usually "crash" or worse).

Share this post


Link to post
Share on other sites
It only crashes if you access memory the process isn't allowed to access (protection fault) or you overwrite memory outside your array occupied by other data which in turn leads to crashes. Accessing the memory outside in itself won't make anything crash (except in the protection fault case).

So it's pretty much a crap shoot whether you'll get a crash or not. Obviously it's not healthy to write outside since you'll be overwriting other vars/data occupying that memory.

Share this post


Link to post
Share on other sites
If you've studied "the stack" in comp-sci, we can pretend that inside your function, the stack might look like this:
bottom of the stack
...
previous stack info
return value storage (int)
return address
fn[0] (int)
fn[1] (int)
fn[2] (int)
fn[3] (int)
fn[4] (int)
unused stack memory
...


If the stack was laid out like this, then when you write to fn[10], you would be writing to as-of-yet-unused stack memory.

In this case, it's entierly likely that as "fn[10]" lives in unallocated stack memory, it's value would be overwritten by subsequent function calls. e.g. this could happen:
int main()
{
int fn[5];
fn[10] = 999;
cout << fn[10] << endl; //prints 999
SomeFuncThatDoesLotsOfStuffOnTheStack();
cout << fn[10] << endl; //prints 1337
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Hodgman
If you've studied "the stack" in comp-sci, we can pretend that inside your function, the stack might look like this:
bottom of the stack
...
previous stack info
return value storage (int)
return address
fn[0] (int)
fn[1] (int)
fn[2] (int)
fn[3] (int)
fn[4] (int)
unused stack memory
...


If the stack was laid out like this, then when you write to fn[10], you would be writing to as-of-yet-unused stack memory.

In this case, it's entierly likely that as "fn[10]" lives in unallocated stack memory, it's value would be overwritten by subsequent function calls. e.g. this could happen:*** Source Snippet Removed ***


if we're talking a normal x86 compatible system at least, the stack grows downward in memory addresses, ie. "push" does a ESP=ESP-4. That means that local vars will be allocated earlier in memory than all params, return addresses and all previous functions in call stack. Overwriting that array as a local function variable will mess up return addresses and whatnot. Basically the mem should look something like (potential padding aside, that the compiler might add between local vars and return addr in debug mode, and leaving out function params):


addr[ 4] fn[0]
addr[ 8] fn[1]
addr[12] fn[2]
addr[16] fn[3]
addr[20] fn[4]
addr[24] return address
addr[28] calling function's local vars
addr[??] calling function's return addr

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!