Чем отличается управление памятью в Java и C#?

Я читал 2010 CWE/SANS Top 25 самых опасных ошибок программирования и одна из записей предназначена для Буферное копирование без проверки размера входных данных. Он предлагает использовать язык с функциями для предотвращения или смягчения этой проблемы и говорит:

Например, многие языки, выполняющие собственное управление памятью, такие как Java и Perl, не подвержены переполнению буфера. Другие языки, такие как Ada и C#, обычно обеспечивают защиту от переполнения, но программист может отключить эту защиту.

Я не знал, что Java и C# существенно различаются в отношении управления памятью. Как получилось, что Java не подвержена переполнению буфера, а C# защищает только от переполнения? И как можно отключить эту защиту в C#?


person David Johnstone    schedule 17.03.2010    source источник


Ответы (2)


java не поддерживает необработанные указатели (строго говоря, не поддерживает арифметику указателей).

В C# можно использовать небезопасный код и указатели, а также неуправляемую память, что делает возможным переполнение буфера. См. ключевое слово unsafe.

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

person Mitch Wheat    schedule 17.03.2010
comment
+1 С точки зрения программиста, вы отключаете защиту, используя ключевое слово unsafe. Также стоит учитывать точку зрения ИТ-администратора, которая заключается в том, что вы можете предотвратить отключение защиты приложениями с помощью своей политики безопасности. - person MarkJ; 17.03.2010

Хорошие ответы. Я бы добавил, что Java зависит от использования ячеек памяти стека или кучи. С# тоже. Идея использования необработанных указателей является дополнением к C#, которое исходит из его кода C. Хотя C# и C/C++ не являются одним и тем же языком программирования, они имеют некоторые общие черты семантики. Идея использования «небезопасного» кода позволяет избежать хранения больших объектов в куче, где память ограничена примерно 2 ГБ на экземпляр среды выполнения (для C# на CLR, для Java на экземпляр JVM) без резкого снижения производительности из-за сборки мусора. В некоторых случаях вы можете использовать способность C# использовать небезопасные или управляемые вручную указатели памяти, чтобы обойти тот факт, что существует не так много сторонних инструментов для решения таких проблем, как кэширование вне кучи.

Я хотел бы предупредить, что если вы используете небезопасный код, обязательно ознакомьтесь с «Одноразовыми типами» и «Финализаторами». Это может быть довольно продвинутой практикой, и последствия неправильного удаления ваших объектов такие же, как и с кодом C... ужасная УТЕЧКА ПАМЯТИ. Последствия: у вас закончилась память для вашего приложения, и оно падает (нехорошо). Вот почему С# не разрешает это по умолчанию и что вам необходимо переопределить любое использование управляемых вручную указателей с помощью ключевого слова «небезопасно». Это гарантирует, что любая память, обрабатываемая вручную, является преднамеренной. Наденьте шляпу C-кода, когда имеете дело с ключевым словом «небезопасно».

Отличная ссылка на это была в главе «Понимание времени жизни объекта» в «Pro C# 2010 и платформа .Net» Эндрю Троелсена. Если вы предпочитаете ссылки в Интернете, см. веб-сайт MSDN Реализация Finalize и Dispose для очистки неуправляемых ресурсов

Последнее замечание: неуправляемая память освобождается в финализаторе вашего объекта (~ObjectName(){...}). Эти шаблоны увеличивают производительность, поэтому, если вы имеете дело со сценариями с более низкой задержкой, вам может быть лучше, если объекты будут легкими. Если вы имеете дело с человеческой реакцией, вы должны учитывать это там, где это абсолютно необходимо.

person Zack Jannsen    schedule 20.03.2012