dotSITE
Work in Murano Software. Учебник по C# Шаблоны проектирования
новости материалы решения форумы группы настройки/о проекте

Небезопасный код

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

Основной возможностью является прямое обращение к памяти (конечно, настолько прямое насколько это позволено процессу), что позволяет выполнять некоторые опреации заметно быстрее. Но в большинстве случаев использование небезопасного кода неоправданы, особенно если учесть дополнительные проверки, совершаемые при выходе из такого блока.

В качестве примера раскроем стандартный пример из MSDN - он использует снандартную функцию Win32 API и вынужден использовать указатели, так как эта функция получает указатель в качестве параметра:

using System;
using System.Runtime.InteropServices;
using System.Text;

class FileRead
{
   const uint GENERIC_READ = 0x80000000;
   const uint OPEN_EXISTING = 3;
   int handle;

   public FileRead(string filename)
   {
       // Эта функция открывает существущийй файл на диске для чтения
       handle = CreateFile(filename,
                           GENERIC_READ,
                           0, 
                           0,
                           OPEN_EXISTING,
                           0,
                           0);
   }

   // Импортируем Win32-функцию CreateFile
   [DllImport("kernel32", SetLastError=true)]
   static extern unsafe int CreateFile(
      string filename,
      uint desiredAccess,
      uint shareMode,
      uint attributes,   // really SecurityAttributes pointer
      uint creationDisposition,
      uint flagsAndAttributes,
      uint templateFile);

   // Импортируем Win32-функцию ReadFile
   [DllImport("kernel32", SetLastError=true)]
   static extern unsafe bool ReadFile(int hFile,
      void* lpBuffer, int nBytesToRead,
      int* nBytesRead, int overlapped);

   // Импортируем Win32-функцию GetLastError
   [DllImport("kernel32", SetLastError=true)]
   static extern int GetLastError();

   // Этот метод помечен как unsafe, так как он использует указатели. 
   // Можно также пометить как unsafe лишь блок кода - нуно заключить его в блок unsafe {...}
   public unsafe int Read(byte[] buffer, int index, int count) 
   {
      int n = 0;

      // Блок fixed запрещает передвигать переменную в памяти, чтобы указатель на нее не изменился
      fixed (byte* p = buffer) 
      {
         ReadFile(handle, p + index, count, &n, 0);
      }
      return n;
   }
}

class Test
{
   public static void Main(string[] args)
   {
       FileRead fr = new FileRead(args[0]);

       byte[] buffer = new byte[128];
       ASCIIEncoding e = new ASCIIEncoding();

      // Читаем весь файл блоками по 128 байт      
      while (fr.Read(buffer, 0, 128) != 0)
      {
          Console.Write("{0}", e.GetString(buffer));
      }
   }
}
    

<< Предыдущая

Контакт Реклама на сайте Спонсорам Веб мастерам

Лицензионное соглашение - © 2000-2012 dotSITE
Хостинг .NET предоставлен PARKING.RU
Поддержку сайта осуществляет Murano Software Inc., Offshore software development