Небезопасный код и указатели 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Небезопасный код и указатели



Для обеспечения строгой типизации и безопасности C# по умолчанию не поддерживает арифметические операции над указателями. Однако с помощью ключевого слова unsafe можно определить небезопасный контекст для использования указателей. Дополнительные сведения об указателях см. в разделе Типы указателей.

Примечание.
В среде CLR небезопасный код называют непроверяемым. Небезопасный код в C# не обязательно представляет опасность. Это просто код, безопасность которого не может быть проверена средой CLR. Поэтому CLR выполнит этот код, только если он находится в полностью надежной сборке. При использовании небезопасного кода необходимо обеспечить гарантию того, что он не создаст угрозу безопасности и не вызовет ошибки указателей.

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

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

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

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

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

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

· Для компиляции небезопасного кода в 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. Дополнительные сведения см. в разделе CharSet.

Еще одним распространенным массивом фиксированного размера является массив 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

 


Типы указателей

В небезопасном контексте тип может быть типом указателя, типом значения или ссылочным типом. Объявления типа указателя выполняется одним из следующих способов:

type* identifier; void* identifier; //allowed but not recommended

Любой из следующих типов может быть типом указателя.

· sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal или bool.

· Любой тип enum.

· Любой тип указателя.

· Любой пользовательский тип структуры, содержащий поля только неуправляемых типов.

Типы указателей не наследуют от объектов, не существует преобразований между типами указателей и object. Кроме того, для указателей не поддерживается упаковка и распаковка. Впрочем, можно выполнять преобразования между различными типами указаний, а также между типами указателей и целыми типами.

При объявлении нескольких указателей в одном объявлении знак * записывается только с нижележащим типом, а не в качестве префикса с каждым именем указателя. Пример.

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

Указатель не может указывать на ссылку или на структуру, содержащую ссылки, поскольку для ссылки на объект невозможен сбор мусора, даже если на нее указывает указатель. Сборщик мусора не отслеживает наличие указателей любых типов, указывающих на объекты.

Значением указателя переменной типа myType* является адрес переменной типа myType. Ниже приведены примеры объявлений типов указателей.

Пример Описание
int* p p — указатель на целое число
int** p p — указатель на указатель на целое число
int*[] p p — одномерный массив указателей на целые числа
char* p p — указатель на знак
void* p p — указатель на неизвестный тип

The pointer indirection operator * can be used to access the contents at the location pointed to by the pointer variable. For example, consider the following declaration:

int* myVariable;

The expression *myVariable denotes the int variable found at the address contained in myVariable.

You cannot apply the indirection operator to a pointer of type void*. However, you can use a cast to convert a void pointer to any other pointer type, and vice versa.

A pointer can be null. Applying the indirection operator to a null pointer causes an implementation-defined behavior.

Be aware that passing pointers between methods can cause undefined behavior. Examples are returning a pointer to a local variable through an Out or Ref parameter or as the function result. If the pointer was set in a fixed block, the variable to which it points may no longer be fixed.

The following table lists the operators and statements that can operate on pointers in an unsafe context:

Operator/Statement Use
* Performs pointer indirection.
-> Accesses a member of a struct through a pointer.
[] Indexed a pointer.
& Obtains the address of a variable.
++ and -- Increments and decrements pointers.
+ and - Performs pointer arithmetic.
==,!=, <, >, <=, and >= Compares pointers.
stackalloc Allocates memory on the stack.
fixed statement Temporarily fixes a variable so that its address may be found.

 


Косвенный оператор указателя * можно использовать для доступа к содержимому, на которое указывает переменная указателя. В качестве примера рассмотрим следующее объявление:

int* myVariable;

Выражение *myVariable обозначает переменную int, находящуюся по адресу, содержащемуся в myVariable.

Невозможно использовать косвенный оператор для указателя типа void*. Однако можно использовать приведение для преобразования указателя типа void в любой другой тип и наоборот.

Указатель может иметь значение null. При применении косвенного оператора к указателю со значением null результат зависит от конкретной реализации.

Обратите внимание, что при передаче указателей между методами может возникнуть непредусмотренное поведение. В примерах указатель возвращается в локальную переменную через параметр Out или Ref либо в виде результата функции. Если указатель был указан в фиксированном блоке, переменная, на которую он указывает, больше не может быть фиксированной.

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

Оператор Действие
* Косвенный оператор указателя.
-> Доступ к члену структуры через указатель.
[] Индексирование указателя.
& Получение адреса переменной.
++ и -- Приращение и уменьшение указателей.
+ и - Арифметические действия указателя.
==,!=, <, >, <= и >= Сравнение указателей.
stackalloc Выделение памяти в стеке.
Оператор fixed Временная фиксация переменной, чтобы можно было найти ее адрес.

 


Pointer Conversions

The following table shows the predefined implicit pointer conversions. Implicit conversions might occur in many situations, including method invoking and assignment statements.



Поделиться:


Последнее изменение этой страницы: 2017-01-19; просмотров: 343; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.142.119.241 (0.021 с.)