19 смертных грехов, угрожающих безопасности программ - страница 35

Шрифт
Интервал


Поняв, что пытается сказать компилятор, вы хотя бы задумаетесь, есть ли в вашем коде реальная проблема. К сожалению, возможности компилятора ограничены. Если бы в предыдущем примере вы избавились от ошибки, объявив a, b и с как целые со знаком, то появилась бы возможность переполнения, а компилятор ничего не сказал бы.

Еще одна приятная особенность С# состоит в том, что он по мере необходимости пользуется 64–разрядными целыми числами. Например, следующий код дал бы неверный результат на С, но правильно работает на С#:

int i = -1;

uint j = 0xffffffff; // наибольшее положительное 32-разрядное целое

if(i == j)

Console.WriteLine("Отлично!");

Причина в том, что С# приведет операнды к типу long (64–разрядное целое со знаком), который позволяет точно сохранить оба числа. Если вы решите пойти дальше и проделать то же самое с числами типа long и ulong (в С# оба занимают 64 разряда), то компилятор сообщит, что необходимо явно преобразовать их к одному типу. По мнению авторов, стандарт C/C++ следует уточнить: если компилятор поддерживает операции над 64–разрядными значениями, то он должен в этом отношении вести себя так же, как С#.

Ключевые слова checked и unchecked

В языке С# есть ключевые слова checked и unchecked. Можно объявить checked–блок:

byte a = 1;

byte b = 255;

checked

{

byte c = (byte)(a + b);

byte d = Convert.ToByte(a + b);

Console.Write("{0} {1}\n", b+1, c);

}

В данном примере приведение а + b от int к byte возбуждает исключение. В следующей строке, где вызывается Convert.ToByte, исключение возникло бы и без ключевого слова checked, но его наличие приводит к возбуждению исключения еще и при вычислении аргументов метода Console.Write(). Поскольку иногда переполнение целого допускается намеренно, то имеется также ключевое слово unchecked, отключающее контроль на переполнение.

Слова checked и unchecked можно также использовать для включения или отключения контроля в одном выражении:

checked (с = (byte) (Ь + а));

И наконец, включить контроль можно с помощью флага /checked компилятора. Если этот флаг присутствует, то нужно явно помечать словом unchecked участки кода или отдельные предложения, в которых переполнение допустимо.

Греховность Visual Basic и Visual Basic .NET

Visual Basic регулярно претерпевает кардинальные модификации, а переход от Visual Basic 6.0 к Visual Basic .NET стал самым значительным шагом со времен введения объектной ориентированности в Visual Basic 3.0. Одно из самых фундаментальных изменений связано с целочисленными типами (см. табл. 3.1).