2010-10-30 10 views
5

Se debe establecer StringBuilder.Capacity en la cantidad máxima de caracteres .NET, sin tener en cuenta la terminación nula, o se debe establecer uno más alto para reservar espacio para un terminador nulo cuando se usa P/Invoke.¿Cuál es la forma correcta de establecer StringBuilder.Capacity cuando se usa P/Invoke?

La reacción natural es que se debe establecer uno más alto, pero parece que se espera que P/Invoke compense automáticamente. De hecho, este es en realidad documentada aquí: http://msdn.microsoft.com/en-US/library/s9ts558h(v=VS.100).aspx

La razón de esta pregunta es que la mayoría de los ejemplos no son estrictamente coherente con la documentación anterior. Casi siempre se codifican:

StringBuilder sb = new StringBuilder(dotNetChars + 1); 
SomeWindowsAPI(sb, sb.Capacity); 

En lugar de:

StringBuilder sb = new StringBuilder(dotNetChars); 
SomeWindowsAPI(sb, sb.Capacity + 1); 

(Soy consciente de que algunas API manejan el parámetro de tamaño de búfer diferente Supongamos que la API se encarga de esta forma común del mosto, como GetFullPathName.: http://msdn.microsoft.com/en-us/library/aa364963(v=VS.85).aspx)

Usar una expresión con sb.Capacity directamente en la llamada API parece ser una buena práctica para evitar una falta de coincidencia. El problema es si agregar o no el +1 es correcto.

Mire a su alrededor. Probablemente descubrirá que el único lugar que muestra sb.Capacity + 1 es la documentación de MSDN.

Por supuesto, se puede asignar precaución con un búfer más grande que el estrictamente necesario, pero me gustaría saber el consenso sobre cómo hacerlo.

Respuesta

0

dentro del constructor de StringBuilder, la capacidad se usa como esto:

m_ChunkChars = new char[capacity]; 

Esto se utiliza junto con el campo m_ChunkLength para determinar el contenido de la StringBuilder. Esto solo describe los personajes reales, sin incluir un carácter de terminación.

Así que su respuesta es + 1 no es necesario.

+1

¿Pero qué hace P/Invoke con esto? Si P/Invoke solo pasa la dirección del primer carácter en ese conjunto a la función externa, entonces el conjunto es 1 demasiado corto para el terminador nulo. –

+0

Las cadenas se organizan para pinvoke y el marco agrega automáticamente cosas como '\ 0'. Creo que en este caso, no tiene que tener eso en cuenta. –

0

Probablemente hay una cierta cantidad de programación de culto a la carga. Alguien le pregunta si la memoria se debe asignar a las cuerdas, si responde "longitud + 1" en lugar de longitud. En lugar de leer la documentación para las nuevas circunstancias en las que se le pregunta acerca de la memoria para asignar para cadenas, el desarrollador simplemente "se equivoca en el lado seguro" y pasa en longitud + 1. Otros que leen ese código infieren la misma regla y la práctica se extiende. No tiene que ser correcto pasar de persona a persona, con la probabilidad razonable de que sea correcto y no sea activamente dañino.

2

Me doy cuenta de que ya tiene respuestas de cinco años, pero en mi opinión no responden realmente a la pregunta, básicamente alejan el problema potencial sin verificar si hacerlo es correcto.

La documentación de MSDN garantiza que el Marshaller se asegurará de que haya espacio suficiente para almacenar el Capacity completo del StringBuilder más un terminador nulo adicional.Citando Default Marshaling for Strings:

de longitud fija de Cuerda tampones

[...]

La solución es pasar un buffer StringBuilder como argumento en lugar de una cadena. Un StringBuilder puede ser desreferenciado y modificado por el destinatario, siempre que no supere la capacidad del StringBuilder. También se puede inicializar a una longitud fija. Por ejemplo, si se inicializa un tampón StringBuilder a una capacidad de N, el contador de referencias proporciona una memoria intermedia de tamaño (N +1) caracteres. Las cuentas +1 por el hecho de que la cadena no administrada tiene un terminador nulo, mientras que StringBuilder no lo hace.

[...]

Así que usted no tiene que preocuparse por la adición de uno con la capacidad, el contador de referencias ya se va a hacer esto para usted.

Cuestiones relacionadas