API设计 - 分配输出?

wj3*_*j32 6 c api api-design

C API函数分配输出或让用户指定输出缓冲区是一个好主意吗?例如:

BOOL GetString(
    PWSTR *String
    );
...
PWSTR string;
GetString(&string);
Free(string);
Run Code Online (Sandbox Code Playgroud)

VS

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

更具体地说,我想知道为什么Win32 API主要使用第二种情况(例如GetWindowText,LookupAccountSid).如果API函数知道输出有多大,为什么用户会尝试猜测输出大小?我找不到有关为何使用第二种情况的任何信息.

另外:LookupAccountSid示例特别糟糕.在内部,它使用LSA API,为调用者分配输出.然后LookupAccountSid让用户在只能从LSA返回输出时分配缓冲区(并猜测正确的缓冲区大小)!为什么?

Jar*_*Par 6

Win32 API不预先分配缓冲区,因为它希望为调用代码提供如何提供缓冲区的选择.它允许它们提供堆栈和各种基于堆的缓冲区.有几个地方提前知道缓冲区的最大大小,开发人员希望使用基于堆栈的缓冲区的简单性.

文件系统是路径不会超过的最佳示例MAX_PATH.所以而不是分配+免费.开发人员只是声明一个基于堆栈的缓冲区.

使C API分配内存的优点是它简化了调用模式.Win32模式的缺点是大多数时候你最终都会调用API两次.第一次确定缓冲区的大小,然后第二次用适当大小的缓冲区.使用API​​分配的缓冲区只需要一次调用.

不利的一面是你从调用者那里拿走了分配的选择.此外,您必须传达您的选择,以便他们正确地释放API(例如,窗口可以从几个不同的地方分配).

  • 我注意到在你自己的函数中包装两个调用加上分配是如此简单,简化调用模式是一个非常小的问题.如果您只打算提供一个版本的API,那么它必须更灵活. (3认同)