我的函数应该复制`char *`-arguments吗?

时间:2011-08-30 16:36:46

标签: c string conventions

每当我有一个带有c-string的函数,并希望将其值存储在链表中时,我应该这样做......

void add(char* str)
{
    node *n = malloc(sizeof(node));
    n->value = str;
}

或者更确切地说......

void add(char* str)
{
    node *n = malloc(sizeof(node));
    char* copy = malloc(strlen(str)+1);
    strcpy(copy, str);
    n->value = copy;
}

提前致谢。

3 个答案:

答案 0 :(得分:7)

这实际上取决于参数的来源,以及你对这些论点的意图。

如果您知道作为参数传递的字符串始终在链表的整个生命周期内可用,并且它们未被修改或释放,或者没有任何会产生影响链接的副作用的函数 - 列表,然后你可以简单地复制指针,而不是复制整个字符串。

如果上述任何一个不成立(我的意思是如果你不知道上述其中一个的答案),那么复制整个字符串会更安全。

一些具体的例子:

  • 您正在开发一个小应用程序,它读取csv文件,将值存储在链表中进行排序,然后将值写回xml文件:您可以控制字符串的整个生命周期,你不必复制它们。

  • 您正在编写一个链接列表库,可能会在网上发布,可能会被数百名活跃在各种领域的人使用:您不知道会将什么内容传递到您的图书馆,您不会知道库用户是否会在操作链表之前释放字符串,然后复制整个字符串。

还要注意,这种设计决策在某处有更好的记录:作为开发人员,您有责任明确您的函数将存储指针而不复制字符串,或者您将复制字符串并需要其他函数打电话来释放记忆。 (这称为design by contract:你在使用你的函数的代码和函数本身之间建立一个契约,你最好尊重它,否则你会遇到问题,以数据损坏或软件崩溃的形式)。明确意图的一种可能方法是使用适当放置的const关键字。

答案 1 :(得分:1)

str的所有权是多少?它是带动态数据的malloc ed缓冲区吗?在程序中调用add是否拥有指向链表的指针?

没有正确的答案,因为它取决于str的使用方式。

答案 2 :(得分:0)

我宁愿选择第二种选择,因为: - - 即使它有效,代码也无法维护 - 如果删除原始字符串str,则第一个选项会为悬空指针留下很大的间隙。无法确定程序中实际生成了多少指针str副本。 - 任何内存工具也会抱怨,导致输出膨胀,因此很难调试任何实际的内存问题