2013-04-26 11 views
9

Moje zrozumienie (które może być błędne) polega na tym, że w języku C# po utworzeniu łańcucha zostaje on internowany do "puli internującej". Zachowuje to odniesienie do ciągów, dzięki czemu wiele tych samych ciągów może współużytkować pamięć operacyjną.Jak zapobiegać internowaniu łańcucha znaków?

Jednak przetwarzam wiele ciągów znaków, które najprawdopodobniej są unikatowe i muszę je całkowicie usunąć z pamięci operacyjnej, gdy skończę pracę z każdym z nich i nie jestem pewien, w jaki sposób buforowane odwołanie zostanie usunięte aby odśmiecacz mógł po prostu usunąć wszystkie dane ciągów z pamięci. Jak mogę zapobiec internowaniu napisu w tej pamięci podręcznej lub w jaki sposób mogę go usunąć lub usunąć z niego ciąg znaków, aby z pewnością został usunięty z pamięci operacyjnej?

+0

Jaka jest Twoja motywacja do chęci zrobienia czegoś innego niż domyślne zachowanie? –

+1

Po prostu pozwól, aby GC wykonał swoją pracę. – ken2k

+6

Nie każdy ciąg zostaje internowany, [tylko ciągi literalne] (http://stackoverflow.com/questions/8509035/why-only-literal-strings-saved-in-the-intern-pool-by-default). –

Odpowiedz

4

Jeśli chcesz usunąć ciągi z pamięci ze względów bezpieczeństwa, użyj SecureString.

W przeciwnym razie, jeśli nie ma żadnych odniesień do ciągu w dowolnym miejscu, GC czyści go mimo to (nie będzie już internowany), więc nie musisz się martwić o interning.

I oczywiście tylko literały łańcuchowe są internowane w pierwszej kolejności (lub jeśli wywołasz String.Intern() jak wspomniano powyżej przez Petra i innych).

+5

@downvoter: Czy możesz wyjaśnić, dlaczego, aby pomóc innym, którzy czytają tę odpowiedź? –

+1

SecureString NIE jest rozwiązaniem. Brzmi to "bezpiecznie", ale jeśli poprawnie przeczytam jego pytanie, nie musi on usuwać ich z pamięci, ponieważ obawia się hakerów lub czegoś. Po prostu chce odzyskać swoją pamięć operacyjną. –

+0

@MartinMulder Nie jest całkowicie jasne z tego pytania, stąd użycie terminu "* if *" w pierwszym wierszu mojej odpowiedzi. –

5

Zastosuj atrybut CompilationRelaxations do całego zespołu (wygląda jedynym możliwym rozwiązaniem jest zabronić internowania na płaszczyźnie montażowej) w następujący sposób:

[assembly: CompilationRelaxations(CompilationRelaxations.NoStringInterning)] 

Więcej informacji na CompilationRelaxations

UPDATE:

Dokumentacja stwierdza, że ​​atrybut:

Oznacza zespół jako niewymagający ciągłego literowania interferencyjnego.

Innymi słowy, nie uniemożliwia kompilatorowi wykonywania ciągów znaków , zapewniając jedynie wskazówkę, że nie jest to wymagane. Dokumentacja jest w tym obszarze trochę skąpa, ale wydaje się, że jest to również , co jest wynikiem w this MSDN forum post.

Od this SO question tego atrybutu

+5

pomocne byłoby poznanie przyczyny downwarda. –

+1

Oznacza zespół jako ** niewymagający ** interakcji ciąg-literowy, co nie jest równoznaczne z informacją, że funkcja powinna być wyłączona http://social.msdn.microsoft. com/Forums/pl-US/clr/thread/c1c1d969-8d6b-4aaf-b7f4-3febedf3cd18/ –

+0

@TimSchmelter zaktualizował odpowiedź z linkiem + wyjaśnienie od powiązanego pytania SO i wspomnianego wątku MSDN. Dzięki –

1

Przed stara się zapobiec interning Proponuję użyć String.IsInterned(), aby dowiedzieć się, czy struny obawiasz się faktycznie internowany w ogóle. Jeśli funkcja zwróci wartość null, Twój ciąg nie jest internowany.

O ile mi wiadomo, ciągi generowane dynamicznie w czasie wykonywania nie są w ogóle internowane, ponieważ nie przyniosłoby to żadnych korzyści związanych z wydajnością.

1

Mówisz do rzeczy:

  • Jesteś przetwarzanie wiele strun, więc mówimy o wartościach uruchomieniowych.
  • Chcesz usunąć ciągi z pamięci po zakończeniu ich przetwarzania.

Domyślnie wartości runtime NIE są internowane. Otrzymujesz ciąg znaków z pliku lub sam tworzysz ciąg znaków, wszystkie mają oddzielną instancję. Możesz internować je za pośrednictwem String.Intern. Ciągi internowania wymagają więcej czasu, ale zużywają mniej pamięci. Zobacz: http://msdn.microsoft.com/en-us/library/system.string.intern.aspx

Łańcuchy wykonawcze są automatycznie usuwane przez GC, jeśli nie ma do nich odniesienia. Internowany będzie miał więcej referencji, ale pod koniec twojego procesu zakładam, że wszystkie referencje zostały usunięte. Mechanizm interningowy nie zachowuje referencji HARD, ale referencję SŁABE. Słaba referencja jest ignorowana przez GC, więc instancja napisu może zostać usunięta. Zobacz: http://msdn.microsoft.com/en-us/library/system.weakreference.aspx

Więc ... żeby to podsumować. Domyślnie twoje ciągi runtime nie są internowane. A jeśli zostaną internowani, nadal będą usuwane przez GC po zakończeniu pracy.

Powiązane problemy