2010-01-19 13 views
5

È una buona idea che le funzioni API C assegnino il loro output o che l'utente specifichi il buffer di output? Per esempio:Progettazione API: allocare l'output?

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 

In particolare mi chiedo il motivo per cui l'API Win32 utilizza principalmente il secondo caso (ad esempio GetWindowText, LookupAccountSid). Se una funzione API sa quanto è grande l'output, perché l'utente prova a indovinare la dimensione dell'output? Non riesco a trovare alcuna informazione sul perché il secondo caso verrebbe utilizzato.

Inoltre: l'esempio LookupAccountSid è particolarmente negativo. Internamente utilizza l'API LSA, che alloca l'output per il chiamante. Quindi LookupAccountSid consente all'utente di allocare un buffer (e indovinare la dimensione del buffer corretta) quando potrebbe restituire l'output di LSA! Perché?

+0

Dipende. Entrambi gli idiomi sono usati. Entrambi hanno vantaggi e svantaggi. –

+0

Quali sono i vantaggi del secondo caso, oltre a essere in grado di utilizzare un buffer basato su stack? – wj32

+0

Consente al chiamante di utilizzare la propria scelta di allocater. Se si assegna memoria e si lascia il chiamante libero, il chiamante deve utilizzare il deallocatore corrispondente, che potrebbe non essere la loro preferenza. La compilazione di un buffer fornito dal chiamante consente loro di scegliere un allocatter appropriato per i loro scopi, piuttosto che basarsi su quello scelto dall'API. –

risposta

5

L'API Win32 non pre-alloca i buffer perché vuole fornire al codice chiamante la scelta su come fornire il buffer. Permette loro di fornire stack e una varietà di buffer basati su heap. Esistono diversi punti in cui la dimensione massima del buffer è nota in anticipo e gli sviluppatori desiderano la semplicità dell'utilizzo di un buffer basato su stack.

Il file system è l'esempio migliore in quanto i percorsi non superano MAX_PATH. Quindi piuttosto che assegnare + gratuitamente. Lo sviluppatore dichiara semplicemente un buffer basato su stack.

Il vantaggio di avere la C API allocare memoria è che semplifica il modello di chiamata. Lo svantaggio del modello Win32 è che la maggior parte delle volte si finisce per chiamare l'API due volte. La prima volta per determinare la dimensione del buffer, quindi la seconda volta con un buffer di dimensioni appropriate. Con un buffer allocato API è necessaria una sola chiamata.

Lo svantaggio è che si toglie la scelta dell'allocazione dal chiamante. Inoltre devi comunicare la tua scelta in modo che possano liberare correttamente l'API (windows per esempio può allocare da più posti diversi).

+3

Notare che è così semplice racchiudere le due chiamate più allocazione nella propria funzione, che semplificando il modello di chiamata è una preoccupazione molto minore. Se hai intenzione di offrire solo una versione dell'API, deve essere la più flessibile. –

1

Il secondo approccio ha diversi vantaggi come

  • Permette chiamanti gestire la durata di allocazioni di memoria
  • Permette chiamanti riutilizzare memoria allocata per diverse chiamate che seguono lo stesso modello
  • Consente chiamanti decidere quale buffer fornire ad es stack o heap.
Problemi correlati