在 C 中释放对象的设计模式

Ins*_*oop 3 c

当用 C 语言编程时,我们通常创建初始化的数据结构,然后在不再需要时将其释放。例如,如果我们想创建一个动态的 double 数组,通常声明

struct vector {
    double *data;
    int size;
    int capacity;
}
typedef struct vector vector;

vector *v_new(int n) {
    vector *v = malloc(sizeof(vector));
    v->data = malloc(n * sizeof(double));
    v->size = n;
    v->capacity = n;
    return v;
}
Run Code Online (Sandbox Code Playgroud)

问题是关于自由函数的常见模式。在 C 语言中,该函数free接受 NULL 指针并且不执行任何操作。以这种方式设计v_free函数是一种常见的模式,还是它们通常期望一个非 NULL 指针?明确地说,您期望这种实现吗?

void v_free(vector *v) {
    if (v != NULL) {
        free(v->data);
    }
    free(v);
}
Run Code Online (Sandbox Code Playgroud)

或者这个?

void v_free(vector *v) {
    free(v->data);
    free(v);
}
Run Code Online (Sandbox Code Playgroud)

提出这个问题是因为我们在法国预科学校开始向本科生教授C语言,而我们在“C设计模式”方面没有那么多经验。

谢谢你的建议。

hyd*_*yde 5

v->data如果为 NULL,则无法访问v。因此,如果有可能发生这种情况,您必须执行检查该情况的版本,最好写为

void v_free(vector *v) {
    if (v != NULL) {
        free(v->data);
        free(v);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果v这里永远不应该为 NULL,那么最好添加一个断言来明确假设:

void v_free(vector *v) {
    assert(v != NULL);
    free(v->data);
    free(v);
}
Run Code Online (Sandbox Code Playgroud)

这样程序员就会注意到他们做错了什么。


请注意,这两个版本都没有检测到悬空指针,即。指向已销毁对象的指针。这包括指向已经释放的内存(即,这里有双重释放)或通过指向不再在范围内的局部变量的指针。