首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C语言中简单变量字符串连接的内存分配

C语言中简单变量字符串连接的内存分配
EN

Stack Overflow用户
提问于 2010-11-07 18:43:18
回答 5查看 953关注 0票数 1

我有以下测试函数来复制和连接可变数量的字符串参数,并自动分配:

代码语言:javascript
复制
char *copycat(char *first, ...) {
    va_list vl;
    va_start(vl, first);
    char *result = (char *) malloc(strlen(first) + 1);
    char *next;
    strcpy(result, first);
    while (next = va_arg(vl, char *)) {
        result = (char *) realloc(result, strlen(result) + strlen(next) + 1);
        strcat(result, next);
    }
    return result;
}

问题是,如果我这样做:

代码语言:javascript
复制
puts(copycat("herp", "derp", "hurr", "durr"));

它应该打印出一个16字节的字符串"herpderphurrdurr"。相反,它会打印出一个42字节的字符串,即正确的16字节加上另外26字节的垃圾字符。

我还不是很确定为什么。有什么想法吗?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-11-07 18:46:43

变量参数列表函数不会神奇地知道有多少个参数,所以您很可能会遍历堆栈,直到碰巧遇到NULL

您要么需要一个参数numStrings,要么在字符串列表后提供一个显式的空终止符参数。

票数 5
EN

Stack Overflow用户

发布于 2010-11-07 18:50:02

你需要在你的列表上有一个标记:

代码语言:javascript
复制
puts(copycat("herp", "derp", "hurr", "durr", NULL));

否则,va_arg实际上不知道何时停止。你得到垃圾的事实纯粹是偶然的,因为你调用了未定义的行为。例如,当我按原样运行你的代码时,我得到了一个分段错误。

可变参数函数,如printf,需要某种形式的指示,说明传入了多少项:printf本身预先使用格式字符串来解决这个问题。

这两个通用方法是count (或格式字符串),当您不能使用其中一个可能的值作为标记(末尾的标记)时,此方法非常有用。

如果您可以使用标记(如指针中的NULL,或非负有符号整数中的-1 ),这通常会更好,这样您就不必计算元素的数量(并且有可能使元素计数和元素列表不同步)。

请记住,puts(copycat("herp", "derp", "hurr", "durr"));是一个内存泄漏,因为您正在分配内存,然后丢失指向它的指针。使用:

代码语言:javascript
复制
char *s = copycat("herp", "derp", "hurr", "durr");
puts(s);
free (s);

是解决这个问题的一种方法,您可能想放入错误检查代码,以防分配失败。

票数 5
EN

Stack Overflow用户

发布于 2010-11-07 18:59:23

我从你的代码中理解的是,你假设一旦每个参数都被“弹出”,va_next就会返回NULL。这是错误的,因为va_next完全没有办法确定参数的数量: while循环将一直运行,直到随机命中一个NULL。

解决方案:提供参数的数量,或者使用附加的"NULL“参数调用函数。

PS:如果你想知道为什么printf不需要这样一个额外的参数,那是因为预期参数的数量是从格式字符串中推导出来的(‘%flag’的数量)

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4117355

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档