Well... that doesn't matter to "standards" enforcers who embrace a
Mandarin mentality.
yeah.
I have never understood how this is such a burden. Just either
globalize any such constraints or pass them as parameters.
the issue is that lots of code either does not check bounds, or stuff
goes out of bounds due to "simple coding errors", like accidentally
allocating either the wrong amount of memory, or calculating the array
index wrong.
to some extent it is possible to use a "tripwire detector" or similar
built into the memory manager, which can detect when code has ran off
the end of an array (either when freeing memory, or periodically based
on a timer or similar and doing a scan over the heap to make sure
everything is still in-order), generally because memory objects may have
"tripwires" before and after them, and in most cases, an overrun will
mangle them, and when detected it is possible to analyze them and write
the results out to a log or similar (the memory manager also keeps track
of things like where memory allocation and free calls come from, and so
can basically say where the offending memory-object is from, ...).
but, it isn't really possible to catch the code which does so in the act
(like with an explicit trap), and sometimes there might still be memory
corruptions due to code which seemingly escapes the tripwire detector
(writes to addresses not directly adjacent to the memory object in
question).
likewise, writes to random (garbage) addresses (such as from
accidentally using uninitialized variables) may often not trap if the
application uses most of the available address space (it only reliably
traps if the address points at an address range owned by the OS).
a few times I had thought it might be nice if, when an uninitialized
variable is used by code, besides just generating a warning or similar,
if it could also set the variable initially to a "known bad" address.
like, to better deal with cases where the programmer has not gone and
faithfully fixed up every "use of uninitialized variable 'foo'" or
"'foo' must return a value" style warning.
well, though in general I try to go and clean them up, but this is not
always reliably done.
That sounds like a good thing.
bounds-checking, in general, yes.
not being smart enough to optimize away some constant-index checks, not
always so good.
luckily, it is easy to side-step: use a pointer to an array, no bounds
checking:
int foo[32];
int *pfoo;
foo[8]=3; //uses bounds checking at runtime...
pfoo=foo;
pfoo[8]=3; //no bounds checking...
in some ways, a totally amazing piece of engineering there...
Doctor, doctor it hurts when I do that....
it can matter for code which tends to be CPU bound...
a particular case where it came up was within a video codec, where these
constant-index array accesses ate lots of clock cycles.
code within video codecs tends to be fairly performance-sensitive, as
wasting too many cycles in a codec can very easily lead to performance
problems... (more so when a person is trying to squeeze speeds of like
300+ megapixels per second out of the thing, like for multiple
concurrent streams or for 4K+ or similar...).
variable indexes could theoretically still be checked, as then it is
doing its job, rather than just being stupid and wasting clock cycles.
in a few cases this has led mostly to just using lots of variables
instead of arrays, like:
int i0, i1, i2, i3, ...;
i8=3;
but, then gets kind of annoying as the compiler's optimizer sometimes
goes and rewrites things in stupid ways.
like sometimes, one will store something to a variable, and the
optimizer is like "hey, I will go inline/repeat this expression every
time that variable is used", which is sometimes not good:
say, the programmer had a specific reason for factoring out the
expression into its own variable (say, because calculating something
once and using a variable can often be cheaper than recalculating it a
bunch of times in a row, ...).
other times, it is like, one writes:
memcpy(dst, src, 8);
and the compiler is like, "I will helpfully rewrite this to":
mov edi, [...]
mov esi, [...]
mov ecx, 8
rep movsb
(*)
and the programmer is left having to manually intervene, as it is
generally preferable to have the compiler generate something like:
mov ecx, [...]
mov edx, [...]
mov [...], ecx
mov [...], edx
or, better yet:
movq xmm0, [...]
movq [...], xmm0
*: actually, "rep movsb" and friends can go "surprisingly fast" for
larger memory copies (several KiB or more), where they can outperform
more generic loops, but this doesn't mean it is the best choice for
small fixed-size copies.
so, sometimes, one is left to wonder if MSVC's code-generator is
brain-damaged, or contains a "cleverness seemingly beyond the
understanding of mortal men".