C中的内存清理:在哪里检查指针?

C中的内存清理:在哪里检查指针?,c,pointers,memory,C,Pointers,Memory,您正在创建一个结构,需要稍后在程序中销毁它。但是,由于某些错误,结构可能实际上没有被分配,因此需要检查指针是否有效(编辑:检查NULL不能确保指针有效,请参阅)。基本上你可以用两种方法来做 检查“顶部”: 主要条款c: struct my_struct* foo = create(); ... if (foo) { destroy(foo); } struct my_struct* foo = create(); ... destroy(foo); mystruct.c: void de

您正在创建一个结构,需要稍后在程序中销毁它。但是,由于某些错误,结构可能实际上没有被分配,因此需要检查指针是否有效(编辑:检查
NULL
不能确保指针有效,请参阅)。基本上你可以用两种方法来做

检查“顶部”:

主要条款c:

struct my_struct* foo = create();
...
if (foo) {
  destroy(foo);
}
struct my_struct* foo = create();
...
destroy(foo);
mystruct.c:

void destroy(struct my_struct* foo) {
  /* Do clean up */
}
void destroy(struct my_struct* foo) {
  if (foo) {
    /* Do clean up */
  }
}
检查“底部”:

主要条款c:

struct my_struct* foo = create();
...
if (foo) {
  destroy(foo);
}
struct my_struct* foo = create();
...
destroy(foo);
mystruct.c:

void destroy(struct my_struct* foo) {
  /* Do clean up */
}
void destroy(struct my_struct* foo) {
  if (foo) {
    /* Do clean up */
  }
}

第一个函数确保用户正确地清理了所有内容,但第二个函数在main.c中提供了更清晰的代码(尽管在这种情况下,“destroy”可能不是该函数的最佳名称)。我真的不能决定我应该遵循哪个原则,我想知道其中一个原则是否有真正的缺点?

让我们假设你正在写一本公共图书馆。如果以C库为例,在大多数函数中,必须向有效对象传递指针(空指针不是)。一个例外是
free
函数(类似于
destroy
函数),该函数允许
free(NULL)
,并对这样的参数执行no操作。

函数
destroy()
应该明确检查是否有任何事情要做

除此之外,编写、编译等所需的代码更少,因为可能有许多调用
destroy()
,但只有一个实例

请注意,
destroy()
在调用指针时无法将其清空:

foo = create ();
/* use foo a lot */

destroy (foo);

/* No matter what destroy() does, foo is unchanged here */
/* and can be dangerously dereferenced to inspect or modify the object, etc. */

检查指针是否为空并不意味着指针是有效的。@LucasHenrique True,也许我应该重新表述一下。请注意,这是一个需要尝试解决的不太常见的问题,因为在一般情况下无法检查指针是否有效。。e、 标准C库不能解决这个问题,如果你把一些无效的东西传递给标准库函数,那么所有的赌注都没有了。您可以假设/document,任何调用方都应该在指针被销毁后将其设置为NULL,并检测传递给您的函数的NULL指针。因此,本质上,我应该执行
foo=destroy(foo)
,并返回
NULL
?@gwj62:这不是一个坏主意,但无法确保代码使用返回值。通过引用传递指针可以做得更好<代码>销毁(&foo)然后相应地更改
销毁。