2010-01-19 40 views
5

C API函數分配它們的輸出還是讓用戶指定輸出緩衝區是一個好主意嗎?例如:API設計 - 分配輸出?

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 

更具體我不知道爲什麼在Win32 API主要使用第二種情況下(例如GetWindowTextLookupAccountSid)。如果一個API函數知道輸出有多大,爲什麼用戶會嘗試猜測輸出大小?我找不到有關爲什麼會使用第二種情況的任何信息。

另外:LookupAccountSid示例特別糟糕。它在內部使用LSA API,它爲調用者分配輸出。然後,LookupAccountSid可以讓用戶分配一個緩衝區(並猜測正確的緩衝區大小),只要它可以返回LSA的輸出!爲什麼?

+0

這取決於。這兩個習語都被使用。兩者都有優點和缺點。 – 2010-01-19 00:51:42

+0

除了能夠使用基於堆棧的緩衝區之外,第二種情況的優點是什麼? – wj32 2010-01-19 00:53:50

+0

它允許調用者使用他們的分配器的選擇。如果您分配內存並將其留給主叫方以釋放,則主叫方需要使用相應的取消分配器 - 這可能不是他們的偏好。填充調用者提供的緩衝區允許他們爲他們的目的選擇合適的分配器,而不是依賴API選擇的分配器。 – 2010-01-19 01:08:54

回答

5

Win32 API不預先分配緩衝區,因爲它想讓調用代碼選擇如何提供緩衝區。它允許他們提供堆棧和各種基於堆的緩衝區。有幾個地方會提前知道緩衝區的最大尺寸,開發人員希望使用基於堆棧的緩衝區的簡單性。

文件系統是路徑不會超過MAX_PATH的最佳示例。所以,而不是分配+免費。開發人員只需聲明一個基於堆棧的緩衝區。

使C API分配內存的好處是它簡化了調用模式。 Win32模式的不利之處在於,你最終多次調用API兩次。第一次確定緩衝區的大小,然後第二次使用適當大小的緩衝區。使用API​​分配的緩衝區只需要一次調用。

但是,不利的一面是,你拿走了來電者的分配選擇。此外,您必須傳達您的選擇,以便他們正確釋放API(例如,窗口可以從多個不同的地方分配)。

+3

我會注意到,將兩個調用和分配放在自己的函數中非常簡單,簡化調用模式是一個非常小的問題。如果你只提供一個版本的API,它必須是更靈活的。 – 2010-01-19 01:51:55

1

第二種方法有像

  • 它可以讓呼叫者管理內存分配的生命週期
  • 它可以讓呼叫者重用爲遵循相同的模式
  • 它可以讓呼叫者不同的呼叫分配的內存的優勢決定提供哪個緩衝區,例如堆棧或堆。