K
Keith Thompson
Shao Miller said:Shao Miller said:MUDFLAP can diagnose stuff that's permitted by C90, such as warning you
that an index used for iteration has gone too far. Usually you want to
index one-past an array, at most. Do the 'for' loops have any problems?
As I'm sure you know, it's legal to construct a pointer one element
past the end of an array, but not to dererence it. Constructing a
pointer before the beginning of an array or more than one element
past the end of it, or deferencing a pointer one past the end of it,
has undefined behavior. I'm not aware of any relevant changes in
this area from C90 to C99 to C11.
Are you saying that Mudflap complains about stuff that's legal *and
has defined behavior* in C90? If it complained about something
like this:
int arr[N];
int *ptr;
for (ptr = arr; ptr < arr + N; ptr ++) {
/* ... */
}
that would IMHO be a serious bug in Mudflap.
(I haven't analyzed the posted code, but from the discussion I don't
think that's what's going on.)
Nah, I tried to be careful and chose to type "index" instead of "point".
The code I was criticizing used both an integer index as well as a
pointer. Their pointer would never point more than one past the array,
but their integer would index two past the array. That seems to be
permitted by C90.
It's permitted (in all versions of the language) for a object
of an integer type to have any value in the range of that type.
That has nothing at all to do with arrays; there's no association
(that a compiler can detect) between a given integer value and
indices into some array object.
That is, unless you actually use the integer value as an index into
a particular array. In that case, exactly the same rules apply as
for pointers, because the indexing operation is defined in terms
of pointer arithmetic.
Concretely:
int arr[10] = { 0 };
int i;
for (i = 0; i < 10; i += 3) {
arr = 42;
}
In successive iterations of the loop, i takes on the values 0, 3,
6, and 9. *After* the loop, i==12, which is a perfectly valid value
for an object of type int. Evaluating `arr` after the loop would
have undefined behavior, but the program doesn't do that so there's
no problem. There could be problems if i iterates past INT_MAX,
but it doesn't do that either.
I seem to recall some bit about this situation being easily detectable
and reportable as a bonus diagnostic, perhaps in the hopes of alerting
the programmer that there's a better way to write their loop without
stepping out of bounds, conceptually.
What would such a diagnostic look like?
Warning: `i' exceeds the bounds of `arr', so evaluating `arr'
would have undefined behavior, but that never happens so I'm not
sure what I'm warning you about.
A similar snippet using pointers *would* cause undefined behavior,
and would be worthy of a warning (though I can't quite persuade
gcc to generate one):
int arr[10] = { 0 };
int *ptr;
for (ptr = arr; ptr < arr + 10; ptr += 3) {
*ptr = 42;
}
return 0;
because it actually constructs the invalid pointer value.
Or am I missing something?