0

On a recent test question I was asked to print the output of the following program. I got the answer correct however this program caused me significant mental anguish as I didn't know what the behavior would be when writing to memory that is out of bounds of an array.

Here is the program under question, the comments are my notes:

#include <stdio.h>

#define MAX 4

void RecordArgs(int x);

int main()
{
    RecordArgs(1);
    RecordArgs(7);
    RecordArgs(-11);
    return 0;
}

void RecordArgs(int x)
{
    static int i = 0;
    int call_count = 0;
    int arg_history[MAX] = {0};
    if (call_count == MAX)
    {
        # call_count is not static and is initialized to 0 on each call
        # as a result, under no circumstance can call_count == MAX and
        # this printf is never executed
        printf("Too many calls to RecordArgs\n");
    }
    else
    {
        # index out of bounds on second/third call (i + call_count will be 4??)  
        arg_history[i + call_count] = x;
        ++call_count;
        ++i;
        for (i = 0; i < MAX; ++i)
            printf("%d ", arg_history[i]);
        printf("\n");
    }
}

And the expected output:

1 0 0 0
0 0 0 0
0 0 0 0

When RecordArgs is called the second and third times where does the 7 and -11 values get written? I tried compiling it under different settings to see if I could get it two write to something it shouldn't but everything I've tried has resulted in that exact output w/o any segfaults.

Jason Keene
  • 1,085
  • 3
  • 10
  • 20
  • 4
    Reading or writing to an array out of bounds is undefined behaviour. Undefined behaviour is a specific term in C/C++, meaning 'the compiler can decide what happens, whatever it wants'. In practice, depending on where the array is placed (stack? heap? etc) it will access others parts of the program's memory it has allocated, random uninitialized data or crash with an access violation. On top of that, what it does in your program can change from compilation to compilation and computer to computer - aka it will do the worst thing possible when least expected. – Patashu Apr 19 '13 at 01:09
  • Very similar question asked [here](http://stackoverflow.com/questions/15646973/how-dangerous-is-it-to-access-an-array-out-of-bounds?rq=1) – gibertoni Apr 19 '13 at 01:16

1 Answers1

2

Expanding on Patashu's comment, segmentation faults occur when you access memory from a page in a way which clashes with the page of memory's permissions. In other words, they occur when you access a page of memory in a way that you're not allowed to. What's possibly occurring in your situation is that you are accessing memory still within the same page on which arg_history is stored, for which you obviously have permission to read and write.

Another possible scenario is that the page of memory right after the one you're working on has the same permissions which allow you to access it the same way.

In any case, this is undefined behavior in C. Although you witness "expected results," that should not indicate to you that the program is correct. In fact, this is a circumstance in which an out-of-bounds error could potentially go unnoticed, if it doesn't cause a segmentation fault.

Jorge Israel Peña
  • 36,800
  • 16
  • 93
  • 123