Исключение, связанное с массивом C ++ при переполнении - "cout" и нет "cout" - PullRequest
2 голосов
/ 19 декабря 2010
#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», а не иначе ??

Спасибо!

Ответы [ 2 ]

5 голосов
/ 19 декабря 2010

Учитывая, что значение не используется, оно, вероятно, оптимизировано компилятором и никогда не извлекается во время выполнения.

2 голосов
/ 19 декабря 2010

РЕДАКТИРОВАТЬ: В ответ на измененную версию вопроса причина, по которой он падает для array2, но не array1, заключается в том, что (по крайней мере, в MSVC) operator<< для char* пытается получить длину указанной строки и в итоге разыменовывает указатель NULL. Вы получаете такое же поведение, если вы делаете:

std::cout << (char*)NULL;

Сбой в этом случае вызван не за пределами доступа, а разыменованием нулевого указателя.


Несмотря на это, в дополнение к тому, что сказал @UncleZeiv, вы можете узнать, что на самом деле делает код, посмотрев выходные данные дизассемблирования вашего компилятора. Например, на VC ++ 2008 я получаю:

        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] и array2[i] (эти две команды не используются), поэтому программа не падает, даже если вы ' теоретически ссылается на что-то за пределами массива и вызывает неопределенное поведение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...