2011-09-25 10 views
5

Quando ho un StringBuilder vuoto con una capacità di 5 e scrivo "ciao, mondo!" ad esso, lo standard C# specifica la nuova capacità dello StringBuilder? Ho una vaga memoria che è il doppio della lunghezza della nuova stringa (per evitare di cambiare la capacità con ogni nuova stringa aggiunta).Come cambia la capacità di StringBuilder?

+4

questo non è specificato in qualsiasi standard, il suo solo un dettaglio di implementazione – BrokenGlass

+0

StringBuilder non fa parte del linguaggio C#. Fa parte delle librerie .net. –

+0

possibile duplicato di [In che modo StringBuilder decide quanto deve essere grande la sua capacità?] (Http://stackoverflow.com/questions/4495855/how-does-the-stringbuilder-decide-how-large-its-capacity-should -be) – bzlm

risposta

15

Dipende dalla versione di .NET di cui si sta parlando. Prima di .NET 4, StringBuilder utilizzava lo standard .NET strategy, raddoppiando la capacità del buffer interno ogni volta che doveva essere ingrandito.

StringBuilder è stato completamente riscritto per .NET 4, ora con ropes. L'estensione dell'allocazione viene ora eseguita aggiungendo un altro pezzo di corda con un massimo di 8000 caratteri. Non abbastanza efficiente come la strategia precedente, ma evita problemi con i grandi buffer che intasano l'heap di oggetti di grandi dimensioni. Il codice sorgente è disponibile dalla fonte di riferimento se si vuole dare un'occhiata più da vicino.

+0

Ci ha incasinato quando abbiamo aggiornato il nostro prodotto da .Net 3.5 a .Net 4.5. Stavamo usando l'oggetto generatore di stringhe come parametro per una chiamata API nativa attraverso l'interoperabilità. Il risultato è stato un sovraccarico del buffer che ha causato il crash del processo. La memoria heap si corrompeva quando l'API nativa restituiva stringhe lunghe. Abbiamo iniziato a fornire una capacità esplicita nel costruttore in modo che il buffer potesse occuparsi delle stringhe lunghe. Sorprendentemente avrebbe dovuto essere interrotto in precedenza anche per stringhe lunghe ma non veniva mai segnalato. qualche trucco in .Net 3.5 quando usiamo il generatore di stringhe come buffer per le API native? – RBT

+0

Questo danneggia l'heap GC in entrambe le versioni di runtime. Tale corruzione non è necessariamente rilevata, devi essere fortunato. Certo, si tende ad avere più fortuna in .NET 4 –

5

Lo standard C# non specifica il comportamento di una classe di libreria BCL poiché non ha nulla a che fare con le specifiche della lingua.

Per quanto ne so, il comportamento effettivo non è definito in alcuna specifica ed è specifico dell'implementazione.

AFAIK, l'implementazione MS raddoppierà la capacità una volta raggiunta la capacità corrente.

Vedere this e this domande SO precedenti.


Aggiornamento:

Questo è stato modificato in .NET 4.0. come descritto da Hans in his answer. Ora vengono utilizzati ropes, aggiungendo altri 8000 caratteri alla volta.

MSDN, è però molto attenti a sottolineare che il comportamento effettivo è implementazione specifica:

Lo StringBuilder alloca dinamicamente più spazio quando richiesto e aumenta la capacità di conseguenza. Per motivi di prestazioni, un oggetto StringBuilder può allocare più memoria del necessario. La quantità di memoria allocata è specifica dell'implementazione.

+2

Non usiamo più la strategia double-when-full. –

+1

@Eric - Grazie per avermi corretto. Quello e la risposta di Hans mi hanno dato maggiori dettagli. – Oded

-1

Nuovo StringBuilder (.NET 4.5 o superiore) alloca un buffer interno m_ChunkChars richiesto dal parametro di capacità:

public StringBuilder(int capacity) { ... m_ChunkChars = new char[capacity]; ... }

Quindi, se la capacità è inferiore a 40K caratteri va sul piccolo oggetto Heap. Tuttavia (contrariamente alla credenza popolare), StringBuilder sarà ancora allocare sul mucchio di oggetti di grandi dimensioni, se, in seguito, che noi chiamiamo sb.Append(...some string larger than 40K chars...); Una possibile soluzione può essere trovata qui: https://github.com/amikunov/Large-Object-Heap-Fix-For-.NET-String-Builder

+1

Questo non ha nulla a che fare con ciò che la domanda sta chiedendo. – Servy