Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp_Prog_Guide.doc
Скачиваний:
16
Добавлен:
16.11.2019
Размер:
6.22 Mб
Скачать

Общие сведения о небезопасном коде

Небезопасный код имеет следующие свойства.

  • Методы, типы и блоки кода могут определяться как небезопасные.

  • В некоторых случаях небезопасный код может повысить производительность приложения за счет удаления проверок границ массива.

  • Использование небезопасного кода рекомендуется при вызове встроенных функций, требующих указателей.

  • Использование небезопасного кода создает угрозу безопасности и стабильной работы.

  • Для компиляции небезопасного кода в C# необходимо, чтобы приложение было скомпилировано с помощью /unsafe.

Fixed Size Buffers

In C#, you can use the fixed statement to create a buffer with a fixed size array in a data structure. This is useful when you are working with existing code, such as code written in other languages, pre-existing DLLs or COM projects. The fixed array can take any attributes or modifiers that are allowed for regular struct members. The only restriction is that the array type must be bool, byte, char, short, int, long, sbyte, ushort, uint, ulong, float, or double.

private fixed char name[30];

Remarks

In earlier versions of C#, declaring a C++ style fixed-size structure was difficult because a C# struct that contains an array does not contain the array elements, but instead contains a reference to the elements.

C# 2.0 added the ability to embed an array of fixed size in a struct when it is used in an unsafe code block.

For example, before C# 2.0, the following struct would be 8 bytes in size where the pathName array is a reference to the heap-allocated array:

public struct MyArray

{

public char[] pathName;

private int reserved;

}

In C# 2.0, a struct can be declared with an embedded array:

public struct MyArray // This code must appear in an unsafe block

{

public fixed char pathName[128];

}

In this structure, the pathName array is of fixed size and location, and can therefore be used with other unsafe code

Буферы фиксированного размера

В языке C# для создания буфера с массивом фиксированного размера в структуре данных можно использовать оператор fixed. Это полезно при работе с существующим кодом, например с кодом, написанным на других языках, ранее созданными библиотеками DLL или проектами COM. Фиксированный массив может принимать любые атрибуты или модификаторы, допустимые для обычных членов структуры. Единственным ограничением является то, что массив должен иметь тип bool, byte, char, short, int, long, sbyte, ushort, uint, ulong, float или double.

private fixed char name[30];

Заметки

В предыдущих версиях языка C# объявление структуры фиксированного размера в стиле C++ было затруднительным, так как структура C# с массивом не содержит элементов массива. Вместо этого в ней присутствуют ссылки на элементы.

В языке C# версии 2.0 появилась возможность встраивания массива фиксированного размера в структуру, если он используется в блоке небезопасного кода.

Например, в версиях языка C# 2.0 размер следующего ключевого слова struct будет равен 8 байтам, если массив pathName является ссылкой на массив с распределением на кучу.

-----

В языке C# версии 2.0 struct можно объявить со встроенным массивом.

public struct MyArray // This code must appear in an unsafe block

{

public fixed char pathName[128];

}

В этой структуре массив pathName имеет фиксированный размер и положение и, следовательно, может использоваться с другим небезопасным кодом.

The size of the 128 element char array is 256 bytes. Fixed size char buffers always take two bytes per character, regardless of the encoding. This is true even when char buffers are marshaled to API methods or structs with CharSet = CharSet.Auto or CharSet = CharSet.Ansi.

Another common fixed-size array is the bool array. The elements in a bool array are always one byte in size. bool arrays are not appropriate for creating bit arrays or buffers.

Note:

Except for memory created by using stackalloc, the C# compiler and the common language runtime (CLR) do not perform any security buffer overrun checks. As with all unsafe code, use caution.

Unsafe buffers differ from regular arrays in the following ways:

  • You can only use unsafe buffers in an unsafe context.

  • Unsafe buffers are always vectors, or one-dimensional arrays.

  • The declaration of the array should include a count, such as char id[8]. You cannot use char id[] instead.

  • Unsafe buffers can only be instance fields of structs in an unsafe context.

Размер массива из 128 элементов char составляет 256 байт. В буферах фиксированного размера char на один символ всегда приходится два байта, независимо от кодировки. Это справедливо даже в том случае, когда буферы char маршализуются в методы API или структуры с CharSet = CharSet.Auto или CharSet = CharSet.Ansi.

Еще одним распространенным массивом фиксированного размера является массив bool. Размер элементов в массиве bool всегда равен одному байту. Массивы bool не подходят для создания битовых массивов или буферов.

Примечание.

За исключением памяти, созданной при помощи stackalloc, компилятор C# и среда CLR не выполняют проверку переполнения буфера безопасности. Как и при работе с любым небезопасным кодом следует проявлять осторожность.

Небезопасные буферы отличаются от обычных массивов следующим:

  • Небезопасные буферы можно использовать в небезопасном контексте.

  • Небезопасные буферы это всегда векторы или одномерные массивы.

  • В объявлении массива всегда должен присутствовать счетчик, такой как char id[8]. При этом char id[] нельзя использовать.

  • Небезопасные буферы могут быть только полями экземпляра структур в небезопасном контексте.

Pointer types

In an unsafe context, a type may be a pointer type, a value type, or a reference type. A pointer type declaration takes one of the following forms:

type* identifier;

void* identifier; //allowed but not recommended

Any of the following types may be a pointer type:

  • sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool.

  • Any enum type.

  • Any pointer type.

  • Any user-defined struct type that contains fields of unmanaged types only.

Pointer types do not inherit from object and no conversions exist between pointer types and object. Also, boxing and unboxing do not support pointers. However, you can convert between different pointer types and between pointer types and integral types.

When you declare multiple pointers in the same declaration, the * is written together with the underlying type only, not as a prefix to each pointer name. For example:

int* p1, p2, p3; // Ok

int *p1, *p2, *p3; // Invalid in C#

A pointer cannot point to a reference or to a struct that contains references because an object reference cannot be garbage collected even if a pointer is pointing to it. The GC does not keep track of whether an object is being pointed to by any pointer types.

The value of the pointer variable of type myType* is the address of a variable of type myType. The following are examples of pointer type declarations:

Example

Description

int* p

p is a pointer to an integer

int** p

p is a pointer to pointer to an integer

int*[] p

p is a single-dimensional array of pointers to integers

char* p

p is a pointer to a char

void* p

p is a pointer to an unknown type