2010-01-19 8 views
5

¿Es una buena idea que las funciones de C API asignen su salida, o que el usuario especifique el búfer de salida? Por ejemplo:Diseño de API: ¿asignar salida?

BOOL GetString(
    PWSTR *String 
    ); 
... 
PWSTR string; 
GetString(&string); 
Free(string); 

vs

BOOL GetString(
    PWSTR Buffer, 
    ULONG BufferSize, 
    PULONG RequiredBufferSize 
    ); 
... 
// A lot more code than in the first case 

Más específicamente me pregunto por qué la API Win32 utiliza principalmente el segundo caso (por ejemplo GetWindowText, LookupAccountSid). Si una función API sabe qué tan grande es la salida, ¿por qué el usuario debe intentar adivinar el tamaño de salida? No puedo encontrar ninguna información sobre por qué se usaría el segundo caso.

También: el ejemplo de LookupAccountSid es especialmente malo. Internamente utiliza la API LSA, que asigna la salida para la persona que llama. Luego, LookupAccountSid hace que el usuario asigne un búfer (y adivine el tamaño de búfer correcto) cuando podría devolver la salida de LSA. ¿Por qué?

+0

Depende. Ambos modismos son usados. Ambos tienen ventajas y desventajas. –

+0

¿Cuáles son las ventajas del segundo caso entonces, además de poder usar un buffer basado en pila? – wj32

+0

Permite a la persona que llama usar su elección de asignador. Si asigna memoria y deja que la persona que llama libere, la persona que llama debe usar el correspondiente contador de direcciones, que podría no ser su preferencia. Llenar un búfer proporcionado por el que llama permite que elijan un asignador adecuado para sus propósitos, en lugar de depender del elegido por la API. –

Respuesta

5

La API de Win32 no asigna previamente los almacenamientos intermedios porque quiere dar al código de llamadas la opción de proporcionar el almacenamiento intermedio. Les permite proporcionar pila y una variedad de almacenamientos intermedios basados ​​en montón. Hay varios lugares donde se conoce el tamaño máximo del buffer por adelantado y los desarrolladores quieren la simplicidad de usar un buffer basado en stack.

El sistema de archivos es el mejor ejemplo ya que las rutas no excederán MAX_PATH. Entonces, en lugar de asignar + gratis. El desarrollador simplemente declara un buffer basado en la pila.

La ventaja de tener la memoria asignada de la API C es que simplifica el patrón de llamadas. La desventaja del patrón Win32 es que la mayoría de las veces terminas llamando al API dos veces. La primera vez para determinar el tamaño del buffer, luego la segunda vez con un buffer de tamaño apropiado. Con un búfer asignado API, solo se necesita una llamada.

La desventaja es que le quita la opción de asignación de la persona que llama. Además, debe comunicar su elección para que puedan liberar correctamente la API (Windows, por ejemplo, puede asignar desde diferentes lugares).

+3

Me gustaría señalar que es tan sencillo ajustar las dos llamadas más la asignación en su propia función, que simplificar el patrón de llamadas es una preocupación menor. Si solo vas a ofrecer una versión de la API, tiene que ser la más flexible. –

1

El segundo enfoque tiene algunas ventajas como

  • Permite llamadas a gestionar el tiempo de vida de las asignaciones de memoria
  • Permite llamadas de reutilizar la memoria asignada para diferentes llamadas que siguen el mismo patrón
  • Permite llamadas para decidir qué buffer proporcionar, por ejemplo pila o montón.
Cuestiones relacionadas