Undefined Behavior & Safety

out-of-bounds array and pointer access

Picture a row of five numbered mailboxes, 0 through 4. If someone tells you 'put this letter in box 7', there is no box 7 — you are reaching past the end of the row into whatever happens to be there: another tenant's mailboxes, the wall, the street. An array in C is exactly such a row of boxes, and reading or writing outside its valid range is called out-of-bounds access. It is one of the most common sources of undefined behavior and the engine behind many security exploits.

In C an array of size n has valid indices 0 through n-1; there is no automatic check that your index stays in range. The language trusts you completely. Writing a[n] (one past the end) or a[-1] or a[1000] reads or overwrites memory that belongs to other variables, to bookkeeping data, or to nothing at all. The same applies to pointers: you may form a pointer one-past-the-end of an array (that exact spot is legal to hold but not to dereference), but anything further out, or dereferencing the one-past-the-end pointer, is undefined behavior. An out-of-bounds READ may leak secret data (this is how the famous Heartbleed bug exposed private keys); an out-of-bounds WRITE may corrupt a neighbouring variable, smash a return address on the stack, or overwrite allocator bookkeeping on the heap, handing control of the program to an attacker.

Why this matters: because there is no built-in bounds check, an out-of-bounds access often does not crash immediately — it quietly corrupts something, and the program limps on until a much later, baffling failure. The crash, if it comes, is a symptom that may appear far from the real bug. The defenses are practical and worth habit-forming: keep the length alongside the array, derive loop bounds from that length rather than hard-coding, validate any index that comes from outside, and run the program under a tool like AddressSanitizer that adds the bounds checks the language omits.

int a[5]; /* valid indices: 0..4 */ for (int i = 0; i <= 5; i++) a[i] = i; /* a[5] is OUT OF BOUNDS: undefined behavior */ /* fix: use < not <=, and derive the count */ int n = sizeof a / sizeof a[0]; /* n == 5 */ for (int i = 0; i < n; i++) a[i] = i;

The <= writes one element past the end. The fix derives the count with sizeof and stops at n-1 using <.

sizeof gives the array's real length only on the array itself; after the array decays to a pointer (e.g. inside a function), sizeof reports the pointer size and the length is lost. Pass the length as a separate argument.

Also called
out-of-bounds accessbuffer over-readbuffer over-write越界存取緩衝區越界