我正在编写一个函数,它返回以空结尾的字符串array.

在大型项目中有没有这样的例子,比如Linux内核:

  • 何时可以安全地假定(文档/自定义)对返回的字符串/字符串数组进行免费调用?
  • 何时对返回的字符串/字符串数组调用FREE不安全/被禁止?

我很乐意探索多个例子,了解更好的最佳实践.

以下是我正在编写的函数的要求:

Description
Allocates (with malloc(3)) and returns an array
of strings obtained by splitting ’s’ using the
character ’c’ as a delimiter. The array must end
with a NULL pointer.

Return value
The array of new strings resulting from the split. NULL if the allocation fails.

也许值得一提的是,函数是拆分的.

推荐答案

在这种情况下,您不需要判断文档就可以对返回任意字符串/字符串数组API做出合理的假设.C字串是ugly,所以你实际上是在谈论三种可能性:

  1. API接受一个字符串,并在该字符串中返回一个指针.显然,它没有分配新的字符串,所以不需要free,但您仍然记录了它在提供的字符串中返回一个指针(您不希望strtok的用户认为它给了他们新分配的子字符串)

  2. API返回一个新字符串,可以是:

    1. 在静态/缓存存储中分配(必须记录,因为它涉及显式释放函数以返回缓存,和/或它本质上是不可重入的且不是线程安全的),或者
    2. 新分配的(必须释放,尽管不总是free个,所以您也需要记录)

除了这些一般情况外,没有可依赖的标准;如果它明显没有分配,则将其记录下来(缺少free就是隐含的),但在所有其他情况下,您必须记录每个函数需要进行的清理(如果有).

当我们讨论字符串数组时,它变得更加复杂.字符串拆分函数可以通过以下三种方式之一合理地实现(对于合理的定义而言):

  1. 一个类似strtok的函数,它就地修改原始字符串(用NULs替换分隔符),并返回一个新分配的指向现有字符串的指针数组,该数组必须是freed,但子字符串不需要是freed(事实上,原始字符串必须保持活动状态,直到使用完数组为止)
  2. 一个天真的解决方案,malloc个指针数组,以及每个子字符串,具有离散的分配.如果他们通常会提供一个自定义释放函数来避免每个调用者重新实现它,free将是一件非常痛苦的事情.与任何其他解决方案相比,它的性能更低,内存开销更大,但它确实意味着您可以单独修改realloc和修改子字符串,这是有优势的.
  3. 结合了#1和#2的特征的优化版本,其中单个批量分配包含所有子字符串指针,后跟子字符串的原始数据.像#1一样,只需要单个free来清理数据,并且作为交换,存储等于输入字符串大小的额外数据(但没有多个分配开销和内存碎片),像#2一样,输入字符串的生命周期 可以保持不变,输入字符串的生命周期 不需要被延长以匹配子字符串指针的生命周期 (作为交换,不能执行子字符串的realloc).

所有这些对于输入字符串的生存期和可变性都有不同的规则,返回值的哪些组件可以修改,如何修改,以及完成后如何清理.没有单一的标准可供 Select ,因此,您必须显式地记录它(对于第二种情况,如果您将清理简化为"调用此释放函数"并提供可重入性保证,则在技术上不需要记录确切的设计,但如果您隐藏这些实现细节,则API使用者无法从该设计的一些独特好处中受益,例如允许realloc和变化子字符串).

C++相关问答推荐

Mbed TLS:OAEP的就地en—/decryption似乎不起作用'

字符数组,字符指针,在一种情况下工作,但在另一种情况下不工作?

找出文件是否包含给定的文件签名

如果包含路径不存在,我的编译器可以被配置为出错吗?(GCC、MSVC)

如何创建一个C程序来存储5种动物的名字,并在用户 Select 其中任何一种动物时打印内存地址?

理解C版宏(看起来像未声明的变量?)

S和查尔有什么不同[1]?

For循环不会迭代所有字符串字符吗?(初学者问题)

如何确保我将使用C标准库函数的函数版本,如&getc";,而不是类似函数的宏版本?

无法识别C编程语言的语法,如书中所示

从不兼容的指针类型返回&&警告,但我看不出原因

如何修复我的qsort()算法?它每次都给出不同的结果

将size_t分配给off_t会产生符号转换错误

我错误地修复了一个错误,想了解原因

C 程序不显示任何输出,但它接受 CS50 Lab1 的输入问题

当另一个指向 const 的指针观察到数据时,通过指针更改数据是否安全?

我正在使用 klib 库 我可以使用 (khash) KHASH_SET_INIT_INT64() 负值作为键.因为我在头文件中看到它使用 unsigned long int

macos/arm64 上地址空间不使用第一位吗?

一元运算符

如何确保 gcc + libc 对于多字节字符串使用 UTF-8,对于 wchar_t 使用 UTF-32?