我只是从基础知识中学习C ++,并且在数组中学到了在C ++中没有对数组进行绑定检查(例如:int data [10],访问数据[12]编译器不会产生任何错误并给出运行时的值,如果可以访问内存)
在练习int和char数组时,我注意到以下区别:
char char_data[10];//char array case
char_data[1] = 'h';
char_data[15] = 'v';//line 1
char_data[11] = '\0';//line 2
int int_data[10];//int array case
int_data[1] = 10;
int_data[15] = 150;//line 3
int_data[11] = 0;//line 4
当我使用 MSVC ++ 14.0 在main
中运行上述代码时,代码编译正常(因为没有在C ++中进行绑定检查),但在char array case
中,代码是崩溃/中断line 2
我将元素等同于'\0'
(当索引超出范围时,它不考虑索引而是值('\0'
))并且生成的程序集为如下:
10: data[15] = 'v'; //(no bound check here)
00CF1FE5 B8 01 00 00 00 mov eax,1
00CF1FEA 6B C8 0F imul ecx,eax,0Fh
00CF1FED C6 44 0D EC 76 mov byte ptr data[ecx],76h
11: data[11] = '\0';//line 2 (bound check here)
00AF1FFA 89 8D F0 FE FF FF mov dword ptr [ebp-110h],ecx
00AF2000 83 BD F0 FE FF FF 0A cmp dword ptr [ebp-110h],0Ah
00AF2007 73 02 jae main+5Bh (0AF200Bh)
00AF2009 EB 05 jmp main+60h (0AF2010h)
00AF200B E8 6C F1 FF FF call ___report_rangecheckfailure (0AF117Ch)
00AF2010 8B 95 F0 FE FF FF mov edx,dword ptr [ebp-110h]
00AF2016 C6 44 15 EC 00 mov byte ptr data[edx],0
此处,如果值不是'\0'
,则不会为rangecheck failure
生成任何程序集。但是,如果我考虑int的情况,当超出范围index 0
('\0'
的值只是0
)时,它不会检查范围。我无法理解这种行为。
这是编译器相关的还是这种行为(绑定检查值是否为\0
)在所有编译器中是否相同?
请帮助!!!
答案 0 :(得分:1)
那么,你想要对数组进行边界检查吗?有一个解决方案,就是使用std::array
,它是标准库的一部分,因为C ++ 11通过标题<array>
。如果将数组定义为:
std::array<int, 10> data;
然后可以像往常一样使用operator[]
实现所有常用的数组访问,但是你也得到了at
函数(documentation here),它将执行范围测试并抛出{ {1}}失败。
std::out_of_range
如果您愿意,欢迎您在try-block中捕获异常。如果你没有抓住,那么你会在导致错误的确切位置得到一个很好的程序崩溃。这比未定义的行为更好。
当然,在普通情况下,你真的不应该使用异常抛出边界检查。特别是在阵列上。你知道它的大小,所以不要做愚蠢的事情,比如访问有效范围之外的值。