this compiles without a warning in VC9 at warning level 4. Why would one NOT consider this a compiler defect?

こ雲淡風輕ζ 提交于 2019-12-05 15:55:39
DigitalRoss

Many compilers have options to error out this kind of thing.

But it's quite traditional and even proper for C compilers to let this go by default. There are multiple reasons for this.

  1. Remember that x[i] and i[x] are the same thing in C. You can even do "string"[2] OR you can do 2["string"] and get the same result. Try it. And this is because x[i] is defined as *(x + i) and once C is just doing pointer arithmetic and then derefing the result of the expression it's not in the compiler's domain to decide that it's going to work or not.

  2. Given that pointer arithmetic is legal, lots of fairly-decent-for-their-day design patterns actually depend on technical subscript violations

    struct s {
        ...bunch of stuff...
        int points[1]; // not really [1]
    };
    ...
    struct s *p = malloc(sizeof (struct s) + someNumber * sizeof(int));
    

    There is code like this running today all over the place...    Update: heh, here is an actual example of the struct hack on stackoverflow.

The compiler is not required to issue warnings for undefined behaviour (even "serious" ones like this). Many compilers have different sets of behaviour that they tend to check for. I think that if you have VSTS, there is some additional security checks that can be enabled so this might be caught by that. Additionally, the compiler can insert runtime checks that will catch this memory overwrite (probably for debug builds), so you should make sure that you have those enabled.

While the example given is pretty simple, to do a good job of static analysis during compilation in general would take considerable code and slow down the compilation (a naive implementation means another pass over the AST).

In a language already often berated for slow compiles.

Letting you be stupid is part and parcel of c++. Compilers that try to save you from yourself are nice, but that is gravy.

FWIW: g++ -Wall also fails to warn.

This warning is issued when a static code analysis is performed on the sources. Static code analysis is not a part of the compiler specification, though (at least as far as I know), and is done by a separate tool.

Here's an overview of the C/C++ code analysis. And the list of warnings covered by the tool.

The reason it doesn't warn about this is that it is very rarely useful. Looking at your code:

int main(){
    int x[2];
    x[2]=0;     
    return 0;
}

We see that the compiler in this case is able to issue a warning, but only because:

  • the array had not yet decayed to a pointer -- in other words, the size information is still available, and
  • you're using a compile-time constant expression to index into the array.

In most real-world code, these two conditions won't hold. The array will almost always be a pointer, in which case the compiler has no size information at all. And equally, you often use a runtime-determined value to index into the array. And again, if you do that, the compiler can't determine if you might go out of bounds.

In other words, while yes, the compiler could issue a warning in this case, and I agree, it might as well, but it would only actually help in very simple toy examples like this one.

If the code had looked like this instead:

void foo(int* x){
    x[2]=0;     
}

or this:

void foo(int i){
    int x[2];
    x[i]=0;
}

the compiler would have been helpless. And those cases are far more common. As has already been mentioned by others, one of the biggest problems with C++ compilers is that they're already slow as hell. Every new warning they have to check for adds more overhead. So is it worth it to add a warning for an error that basically only occurs in little toy examples like this?

As for why you got so bad responses, perhaps the answer is in your question:

I consider this failure to warn a SERIOUS error of omission in VC9,(even more so since an auto variable**!!!!**). Can anyone give me a serious reason to change my mind?

Cut down on the loaded language. Stick to a single exclamation mark. If you sound like you're about to blow a fuse, then people will assume that you are FURIOUS, and then they will tell you that you're overreacting, and that you should just shut up.

Because, the compiler is not your babysitter.

A couple things that might be worth noting:

  1. Unless you have all optimization turned off, this is going to compile away to nothing. The memory will not be written to at all - you might as well have written:

    #pragma warning(push,4)
    int main(){
        return 0;
    }
    #pragma warning(pop)
    
  2. As mentioned elsewhere, doing analysis like this is hard (as in non-computable-trying-to-solve-the-halting-problem). When doing optimizations, it's OK to only do them in the cases where the analysis is easy. When you're looking for warnings, there is a trade-off between being able to find the easy cases, and letting people get dependent on the warnings. At what point is it ok to stop giving the warnings? Yes the locally declared variable being accessed by a constant offset is trivial - but by virtue of being trivial, it's also less important. What if the access is in a trivially inlined function? Or if the access is in a for-loop with constant bounds? These are both easy enough to look for, but they each represent a whole new set of tests, possible regressions, etc... for very little benefit (if any).

I'm not saying that this warning isn't useful - it's just not as clear-cut as you seem to think it is.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!