2010-03-22 4 views
31

Каковы последствия (положительные/отрицательные) использования ключевого слова небезопасного в C# для использования указателей? Например, что происходит с сборкой мусора, каковы приросты/потери производительности, каковы приросты/потери производительности по сравнению с ручным управлением памятью других языков, каковы опасности, в которых ситуация действительно оправдана для использования этого языка функция, дольше компилировать ...?Управление памятью: небезопасное ключевое слово и указатели

ответ

25

Как уже упоминалось Конрадом, есть ситуации, когда небезопасный доступ к памяти в C# полезен. Есть не так много из них, но есть некоторые из них:

  • Манипуляции с Bitmap почти типичный пример, когда вам нужны дополнительные характеристики, которые вы можете получить с помощью unsafe.

  • Interoperability со старым API (например, WinAPI или родным C/C++ DLL) является еще одной областью, где unsafe может быть весьма полезным - например, вы можете вызвать функцию, которая принимает/возвращает неуправляемый указатель.

С другой стороны, вы можете написать большую часть вещей, используя Marshall class, которая скрывает многие из небезопасных операций внутри вызовов методов. Это будет немного медленнее, но это вариант, если вы хотите, чтобы избежать использования unsafe (или если вы используете VB.NET, который не имеет unsafe)

Положительные последствия: Итак, основные положительные последствия существования unsafe в C# - это то, что вы можете написать код более легко (интероперабельность), и вы можете более эффективно писать код (манипулировать с растровым или, возможно, тяжелыми численными вычислениями с использованием массивов), хотя я не уверен о втором).

Отрицательные последствия: Конечно, есть некоторые цена, которую вы должны заплатить за использование unsafe:

  • Non-проверяемый код: C# код, написанный с использованием unsafe функций становится не -verifiable, что означает, что ваш код может каким-либо образом нарушить среду выполнения. Это не является большой проблемой в сценарии с полным доверием (например, неограниченное настольное приложение). У вас просто нет хороших гарантий CLR. Однако вы не можете запускать приложение в ограниченном окружении, таком как общедоступный веб-хостинг, Silverlight или частичное доверие (например, приложение, запущенное из сети).

  • Сборщик мусора также должен быть осторожным при использовании unsafe. GC обычно разрешается перемещать объекты в управляемой куче (чтобы память дефрагментировалась). Когда вы берете указатель на какой-либо объект, вам нужно использовать ключевое слово fixed, чтобы сообщить GC, что он не может перемещать объект до тех пор, пока вы не закончите (что может повлиять на производительность сборки мусора, но, конечно, в зависимости от точного сценария) ,

Мое предположение, что если C# не должны взаимодействовать со старым кодом, он, вероятно, не поддерживает unsafe (и научно-исследовательских проектов, как Singularity, которые пытаются создать более проверяемый операционную систему, основанную на управляемых языках определенно запретить usnsafe код). Однако в реальном мире unsafe полезен в некоторых (редких) случаях.

4

Процитируем Professional C# 2008:

«Две основные причины для использования указателей являются:

  1. назад стандардами - Несмотря на все удобства, предоставляемые .NET- В настоящее время все еще возможно выполнить собственные функции Windows API и для некоторых операций, это может быть только для выполнения вашей задачи. Эти функции API, как правило, , написанные на C, и часто требуют указателей в качестве параметров. Однако в во многих случаях можно написать декларацию DllImport таким образом, что избегает использования указателей; например, с использованием класса System.IntPtr.
  2. Эксплуатационные характеристики - В тех случаях, когда скорость имеет максимальную скорость , указатель может обеспечить маршрут для оптимальной работы. Если вы знаете, что вы делаете, вы можете убедиться, что данные доступны или управляются наиболее эффективным способом. Тем не менее, имейте в виду, что чаще всего , чем нет, есть другие области ваш код, в котором вы можете сделать необходимые показатели эффективности без resoirting указателям. Попробуйте использовать код профилировщика искать узкие места в вашем коде - один поставляется с визуальной Studio 2008.»

И если вы используете указатель кода потребуется более высокий рычаг доверия для выполнения и если пользователь не допускает, что ваш код не будет работать

и завернуть его с последней цитатой:.

«Мы настоятельно рекомендуем против использования указателей излишни becau се это не только труднее писать и отлаживать, но это также не будет в памяти проверки типа безопасности, введенные CLR.»

+0

Можете ли вы опубликовать ссылку (ссылки) для справки? – Alerty

+1

Это книга, которую я купил: http://www.wrox.com/WileyCDA/WroxTitle/Professional-C-2008.productCd-0470191376.html –

+0

Хорошо! Спасибо: D – Alerty

8

Я могу дать вам ситуацию, где стоит использовать :

Мне нужно создать растровый пиксель за пикселем. Drawing.Bitmap.SetPixel() слишком медленный. Поэтому я создаю свои собственные Array растровых данных и использую unsafe для получения IntPtr для Bitmap.Bitmap(Int32, Int32, Int32, PixelFormat, IntPtr).

+1

Да, растровые изображения по-прежнему не имеют быстрого «управляемого» API. –

1

Сбор мусора неэффективен с долгоживущими объектами. Сборщик мусора .Net работает лучше всего, когда большинство объектов выпущено довольно быстро, а некоторые объекты «живут вечно».«Проблема заключается в том, что более длинные живые объекты выпускаются только во время полных сборок мусора, что приводит к значительному снижению производительности. По сути, долгоживущие объекты быстро переходят в поколение 2.

(Для получения дополнительной информации вы можете захотеть читайте на сборщике мусора сборщика .Net: http://msdn.microsoft.com/en-us/library/ms973837.aspx)

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

Реализация какой-либо системы управления памятью, основанной на одном большом байтовый массив, структуры и множество арифметических указателей, теоретически может повысить производительность в ситуациях, когда данные будут храниться в ОЗУ в течение длительного времени.

К сожалению, я не знаю о хорошем способе управления ручным управлением памятью в .Net для объектов, которые будут долговечными. Это в основном означает, что приложения, которые имеют долгоживущие данные в ОЗУ, будут периодически становиться невосприимчивыми, когда они запускают полную сборку мусора всей памяти.

Смежные вопросы