2013-04-26 4 views
9

Мое понимание (что может быть неправильно) заключается в том, что в C# при создании строки он переводится в «внутренний пул». Это сохраняет ссылки на строки, так что несколько одинаковых строк могут совместно использовать операционную память.Как предотвратить интернирование внутри строки

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

+0

Какова ваша мотивация к желанию сделать что-то отличное от поведения по умолчанию? –

+1

Просто дайте GC выполнить свою работу. – ken2k

+6

Не каждая строка становится интернированной, [только буквальные строки] (http://stackoverflow.com/questions/8509035/why-only-literal-strings-saved-in-the-intern-pool-by-default). –

ответ

4

Если вам необходимо удалить строки из памяти из соображений безопасности, используйте SecureString.

В противном случае, если ссылки нет в любом месте, GC все равно очистит его (он больше не будет интернирован), поэтому вам не нужно беспокоиться о интернировании.

И, конечно, только строковые литералы интернированы в первую очередь (или если вы вызываете String.Intern(), как указано выше Петром и другими).

+5

@downvoter: Можете ли вы объяснить, почему, просто чтобы помочь другим, кто прочитал этот ответ? –

+1

SecureString НЕ является решением. Это звучит «безопасно», но если я правильно прочитаю его вопрос, ему не нужно удалять их из памяти, потому что он боится хакеров или чего-то еще. Он просто хочет вернуть свою рабочую память. –

+0

@MartinMulder Это не совсем ясно из вопроса, следовательно, использование термина «* if *» в первой строке моего ответа. –

5

Применить CompilationRelaxations атрибут всей сборки (выглядит единственно возможным решением запретить интернирование на уровне сборки) следующим образом:

[assembly: CompilationRelaxations(CompilationRelaxations.NoStringInterning)] 

Более подробную информацию о CompilationRelaxations

UPDATE:

В документации указано, что атрибут:

Маркирует сборку как , не требующий струн-литерального интернирования.

Другими словами, это не мешает компилятору выполнять стажировку , просто указав, что это не требуется. Документация немного разрежена в этой области, но это также кажется заключением в this MSDN forum post.

С this SO question по этому атрибуту

+5

было бы полезно узнать причину downvote –

+1

Маркирует сборку как ** не требующую ** string-literal интернирование, что не то же самое, что сказать, что функция должна быть отключена http://social.msdn.microsoft. com/Форумы/en-US/clr/thread/c1c1d969-8d6b-4aaf-b7f4-3febedf3cd18/ –

+0

@TimSchmelter обновленный ответ со ссылкой + объяснение из связанного вопроса SO и упомянутого потока MSDN. Спасибо –

1

Перед тем, чтобы предотвратить интернирование я хотел бы предложить использовать String.IsInterned(), чтобы выяснить, является ли струны вы озабоченные фактически интернированы вообще. Если эта функция возвращает значение null, ваша строка не интернирована.

Насколько я знаю, строки, которые генерируются динамически во время выполнения, вообще не интернированы, так как не будет никаких преимуществ в производительности.

1

Вы говорите вещи:

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

По умолчанию значения времени выполнения НЕ интернированы. Вы получаете строку из файла или сами создаете строку, все они имеют отдельный экземпляр. Вы можете использовать их через String.Intern. Внутренние строки занимают больше времени, но потребляют меньше памяти. См.: http://msdn.microsoft.com/en-us/library/system.string.intern.aspx

Строки времени выполнения автоматически удаляются GC, если нет ссылки на них. У интернированного будет больше ссылок, но в конце вашего процесса я предполагаю, что все ссылки удалены. Механизм интернирования не сохраняет HARD-ссылку, но имеет WEAK-ссылку. Слабая ссылка игнорируется GC, поэтому экземпляр строки может быть удален. См .: http://msdn.microsoft.com/en-us/library/system.weakreference.aspx

Итак ... подвести итоги. По умолчанию ваши строки времени выполнения не интернированы. И если они будут интернированы, они все еще будут удалены GC после завершения вашей работы.

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