问题
In this code below I try to access the '-1'th element of an array, I don't get any runtime error.
#include <stdio.h>
int A[10] = {0};
int main(){
A[-1] += 12;
printf("%d",A[-1]);
return 0;
}
When I run the code, it outputs 12
that means it is adding 12 to the non-existent A[-1]. Till today whenever I had tried to access an out-of-bounds element, I had got a runtime-error. I had never tried it on a simple code before.
Can anyone explain why does my code run successfully?
I ran it on my computer and also on ideone, in both the cases it ran successfully.
回答1:
You see, when you allocate a variable like this, it lands on the stack. Stack holds small packages of information about local variables in each function you call, to say it in simple words. The runtime is able to check, whether you exceed the bounds of allocated stack, but not if you write some data in the invalid place on the stack. The stack may look like the following:
[4 bytes - some ptr][4 bytes - A's first element][4 bytes - A's second element] ...
When you try to assign to -1th element of an array, you actually attempt to read four bytes preceding the array (four bytes, because it's an int array). You overwrite some data held on stack - but that's still in valid process's memory, so there are no complaints from the system.
Try running this code in release mode in Visual Studio:
#include <stdio.h>
int main(int argc, char * argv[])
{
// NEVER DO IT ON PURPOSE!
int i = 0;
int A[5];
A[-1] = 42;
printf("%d\n", i);
getchar();
return 0;
}
Edit: in response to comments.
I missed the fact, that A is global. It won't be held in stack, but instead (mostly probably) in .data segment of the binary module, however the rest of explanation stands: A[-1] is still within process's memory, so assignment won't raise AV. However, such assignment will overwrite something, that is before A (possibly a pointer or other part of the binary module) resulting in undefined behavior.
Note, that my example may work and may not, depending on compiler (or compiler mode). For example, in debug mode the program returns 0 - I guess, that memory manager inserts some sentry data between stack frames to catch errors like buffer over/underrun.
回答2:
C and C++ does not have any bounds checking. It is a part of the language. It is to enable the language to execute faster.
If you want bounds checking use another language that has it. Java perhaps?
As your code executes you are just lucky.
回答3:
In C++ (and C), the arrays don't check out of range indices. They're not classes.
In C++11, however you could use std::array<int,10> and at() function as:
std::array<int,10> arr;
arr.at(-1) = 100; //it throws std::out_of_range exception
Or you can use std::vector<int> and at() member function.
来源:https://stackoverflow.com/questions/14640351/why-dont-i-get-a-runtime-error-when-i-access-an-out-of-bounds-element-of-an-arr