避免释放字符串文字

Avoiding freeing a string literal

如果您在 C 中有一个函数,该函数拥有传递给它的任何内容的所有权,例如按值将 struct 添加到向量缓冲区的函数,并且此结构值包含一个成员指针到字符数组(字符串)。

在缓冲区的清理例程中,它应该释放它拥有的字符串,但是如果一些字符串是在运行时分配的,而另一些是在编译时使用字符串文字分配的怎么办。

没有安全和标准(非专有)的方法来检测 char* 是否指向只读内存,那么这个假设的 freeVector 函数与指向的指针有什么关系字符缓冲区?

struct Element {
    int   id;
    char* name;
}

struct Vector {
    size_t maxIndex;
    size_t length;
    struct Element buffer[];
}

void addToVector(struct Vector* vector, struct Element element) {
    // lazy-reallocation logic here if maxIndex => length
    vector->buffer[ vector->maxIndex++ ] = element; // by-value copy
}

void freeVector(struct Vector* vector) {
    for(size_t i = 0; i < vector->maxIndex; i++ ) {
        free( vector->buffer[ i ].name ); // segfault/AV if name is a literal
    }
}

C 的祝福和诅咒是它让这完全取决于你。两种选择是在堆上分配所有内容并定义一个胖指针类型,其中包含一个位来说明每个实例是否需要释放。一个聪明但不可移植的实现可能会使用指针本身的低阶位,因为对于许多体系结构,所有指针的底部 2 位或更多位始终为零。垃圾收集器几乎永远使用这个技巧来区分指针和未装箱的离散类型(fixnums in the biz)。

如果您允许多个指针指向同一对象(想想图形数据结构),那么事情会变得更加复杂或有趣,具体取决于您的观点。为此,您可能需要一个垃圾收集方案:障碍、引用计数、标记和清除、竞技场复制等。其他语言往往会故意为您提供其中之一作为内置或(如在 C++ 中)语言功能旨在支持自己实施一个或多个。对于 C,没那么多...