[ ... ]
Personnaly, the only solution I see is to forget C and C++
and instead use implementations of different programming
languages that provide such run-time checks and error
detection, be it because the implementers of these other
programming languages are not as stubborn as C or C++
implementers, or because those other programming languages
define such an error checking behavior.
Actually, there's a much better solution than changing
languages. Though it's virtually never put to use, x86 CPUs
(for one example) could implement such checks in hardware if
we just put to use what's been there for years.
Specifically, an x86 running protected mode uses segments, and
each segment has a base and a limit. The problem is that right
now, every major OS basically ignores the segments -- they're
all set up with a base of 0 and a limit of 4 GiB (technically
there _are_ segments for which this isn't true, but the stack,
data and code segments are set up this way, so most normal
uses have access to all memory).
Now, it is true that as currently implemented, segments have
some shortcomings -- in particular, there are only 6 available
segment registers, and loading a segment register is a
comparatively expensive operation, so when you use segments
code will usually run a bit slower. The slowdown from doing
the job in hardware is a lot smaller than the slowdown from
doing it in software though.
The other problem is that Intel's current implementation uses
only 16 bit segment registers, so you can only define 65,536
segments at a time. This is mostly an accident of history
though -- the segmentation scheme originated with the 286,
when none of the registers was larger than that. The OS that
ever put it to use was OS/2 1.x, so it's received only the
most minimal updates necessary to allow access to more memory.
Intel's own real time kernels (RTX-86, or something like that,
IIRC) returned a different segment for each allocation, and
required far pointers. I've also used several others that did,
including one on the 80386.
The 80286 and up owed a lot to the experimentation Intel did
with the 432, and were designed to support object based
programming more or less directly---the original intent was that
each object would be in a separate segment, and calls to member
functions would go through a call gate (a type of function call
which changed protection), so that only member functions could
modify the object. (Or something like that---it's been almost
30 years since I read the commercial documentation explaining
this wonder.) In practice, of course, MS-DOS didn't use any of
this, and very quickly, the success of the 80x86 was MS-DOS, so
Intel more or less shut up about this aspect---the fact that the
processor was actually designed with an Ada like environment,
with full protection for everything, in mind.
OTOH, keep in mind that the 286 had four segment registers and
all the associated hardware for checking segment access.
Expanding the hardware to include (for example) 32 segments of
32 bits apiece wouldn't be a huge addition to the size of
today's chips.
Absent that, C++ provides (but doesn't force you to use) about
as good of checking as most other languages. In particular,
things like std::vector include both operator[] and the at()
member function. The former doesn't require bounds checking,
but the latter does.
FWIW, I think that there was some discussion in the committee
about "fixing" arrays in C++, but that in the end, it was felt
that any fix worth doing would break C compatibility too much,
and that the best solution was to just leave them as is, with a
recommendation not to use them, but to replacements from the
library instead.
IMO, the biggest problem is that they should have reversed the
two: the easy, more or less default choice, should also be the
safe one.
It is, in a way. It's a lot easier to use std::vector than it
is to use C-style arrays, and the implementations I usually use
(now that my main platform has migrated to Linux on a PC) do
bounds-checking for vector<>:

perator[], at least with the
compiler options I use. (But I agree that this sort of checking
should be active without any options.)
Bypassing the safety of a bounds check should be what requires
longer code with rather oddball syntax that's easy to spot. In
that case, seeing 'at(x)' during a code inspection would be
almost the same level of red flag as, say, a reinterpret_cast
is.
My pre-standard array classes use "unsafeAt" for unchecked
access

. And I wasn't the only one (since I got the idea from
someone else). I think implementations of the standard library
are allowed to add functions, in which case, the most reasonable
implementation would be:
operator[] Checked, abort in case of error
at() Checked, exception in case of error
unsafe_at() Unchecked.
For that matter, the standard could require this in the next
version, without breaking any code. (But I'm pretty sure that
there's been no such proposal.)