Wil*_*hin 14 c memory-management coding-style
在其他地方的回复中,我找到了以下代码段:
一般来说,让C调用者分配内存而不是被调用者更好 - 因此在我看来strcpy是一个"更好"的函数,而不是strdup.
我可以看到这是一个有效的模式,但为什么它可以被认为更好?遵循这种模式是否有优势?或不?
最近我写了大量的代码,看起来像:
struct foo *a = foo_create();
// do something with a
foo_destroy(a);
Run Code Online (Sandbox Code Playgroud)
如果foo
它不是一个扁平结构,那么我想我可以将所有初始化放在一个步骤中.另外,假设结构应该在堆上.为什么这样做会更好:
struct foo *a = malloc(sizeof(foo));
foo_init(a);
// do something with a
foo_destroy(a)
Run Code Online (Sandbox Code Playgroud)
Ale*_*ski 12
每当你想要一个不透明的结构,并且不想在头文件中公开它的内部.你的foo_create()
例子说明了这一点
另一个例子是Windows API.例如,CreateWindow
给你一个HWND
.您不知道实际WND
结构是什么样的,并且无法触及其字段.
与内核对象句柄相同.例如CreateEvent
给出一个HANDLE
.您只能使用定义良好的API对其进行操作,然后将其关闭CloseHandle()
.
回覆:
struct foo *a = malloc(sizeof(foo));
Run Code Online (Sandbox Code Playgroud)
这要求您struct foo
在标题中定义,从而暴露其内部.如果要在轨道上进行更改,则可能会破坏(错误地)直接依赖其成员的现有代码.
让调用者分配内存的主要优点是它简化了界面,并且调用者拥有内存是完全明确的.正如您的create/destroy示例所示,简化并不是很好.
我更喜欢Dave Hanson在C接口和实现中建立的创建/销毁约定 :
struct foo *foo_new(...); // returns result of malloc()
void foo_free(struct foo **foop); // free *foop's resources and set *foop = NULL
Run Code Online (Sandbox Code Playgroud)
你遵循这样的惯例:
struct foo *a = foo_new();
...
foo_free(&a);
// now `a` is guaranteed to be NULL
Run Code Online (Sandbox Code Playgroud)
这个约定使你不太可能留下一个悬垂的指针.
这两种方法都很好。考虑所有 FILE* 操作函数,它们不允许您自己分配 FILE。
如果您使用 C 进行编程,您通常希望完全控制一切。这意味着让调用者控制分配结构的位置和方式是一件好事。如果我不需要不透明的结构,我个人通常会创建 2 个用于初始化的函数
int foo_init(struct foo *f); // allows the caller to allocate 'f'
//however is suitable
struct foo * new_foo(void); // mallocs and calls foo_init, for convenience.
Run Code Online (Sandbox Code Playgroud)
如果需要,相应的
void foo_free(struct foo *f ); //frees and destroys 'f'
void foo_destroy(struct foo *f); //cleans up whatever internal stuff 'f' has,
// but does not free 'f' itself
Run Code Online (Sandbox Code Playgroud)
在您希望调用者将结构视为不透明的情况下,您将只提供一个 struct foo* new_foo(void); 不公开 struct foo 实现有一些好处:
缺点