#include <iostream>
int main()
{
int array1[10] = {0};
char* array2[10] = {'\0'};
for (int i = 0; i <= 100; i++)
{
std::cout << array1[i]; // This does not crash
//std::cout << array2[i]; // This crashes
array1[i]; // Wont crash here
array2[i]; // nor here, Why? because there is no cout??
}
return 0;
}
好的,对于在这里回答的人,我知道我故意为阵列做了一个溢出。那么为什么程序会在“cout”上崩溃,而不是其他?
谢谢!
答案 0 :(得分:5)
鉴于该值未被使用,它可能会被编译器优化掉,并且在运行时从未真正检索过。
答案 1 :(得分:2)
编辑:在回答问题的更改版本时,array2
而不是array1
崩溃的原因是(至少在MSVC下){{ 1}} for operator<<
尝试获取指向字符串的长度,最后取消引用char*
指针。如果你这样做,你会得到同样的行为:
NULL
这种情况下的崩溃不是由越界访问引起的,而是由空指针引用引起的。
尽管如此,除了@UncleZeiv所说的,你可以通过查看编译器的反汇编输出来判断代码实际上在做什么。例如,在VC ++ 2008上,我得到:
std::cout << (char*)NULL;
换句话说,当你没有对 std::cout<<array1[i]; //--> This crashes
00B2151E mov esi,esp
00B21520 mov eax,dword ptr [i]
00B21523 mov ecx,dword ptr array1[eax*4]
00B21527 push ecx
00B21528 mov ecx,dword ptr [__imp_std::cout (0B2A334h)]
00B2152E call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0B2A318h)]
00B21534 cmp esi,esp
00B21536 call @ILT+405(__RTC_CheckEsp) (0B2119Ah)
std::cout<<array2[i]; //--> So does this
00B2153B mov eax,dword ptr [i]
00B2153E mov ecx,dword ptr array2[eax*4]
00B21542 push ecx
00B21543 mov edx,dword ptr [__imp_std::cout (0B2A334h)]
00B21549 push edx
00B2154A call std::operator<<<std::char_traits<char> > (0B2114Fh)
00B2154F add esp,8
array1[i]; // But not this one
array2[i]; // nor this, Why?
和array1[i]
做任何事情时,编译器没有输出任何指令(两条指令都是无操作),所以程序不会崩溃即使你理论上引用了超出数组边界的东西并调用未定义的行为。