困惑起源
最近在review一段功能代码,看到如下一段。对于strcat部分,在调用后即进行了free操作,会不会有问题,strcat不是把字符串连接上去么?
char* all_field_name = (char*)malloc(sizeof(char)*1024);
memset(all_field_name, 0, 1024);
// ... 省略部分
while (myfields = sql_fetch_field(my_res))
{
char* field_name = (char*)malloc(sizeof(char)*(strlen(myfields->name)+4));
sprintf(field_name, "| %s ", myfields->name);
strcat(all_field_name, field_name);
free(field_name);
}
free(all_field_name)
读源码,解困惑
解决困惑的最好办法,就是查看源代码,看看这个常用库函数到底是怎么操作的。以下代码来源于\linux-6.1-rc1\lib\string.c
#ifndef __HAVE_ARCH_STRCAT
/**
* strcat - Append one %NUL-terminated string to another
* @dest: The string to be appended to
* @src: The string to append to it
*/
char *strcat(char *dest, const char *src)
{
char *tmp = dest;
while (*dest)
dest++;
while ((*dest++ = *src++) != '\0')
;
return tmp;
}
EXPORT_SYMBOL(strcat);
#endif
通过这段代码走读,函数主要的实现步骤如下:
1、函数实现代码的第一行声明了一个很重要的 tmp指针,保留目的字符串的起始地址。接着就可以放心的使用dest,dest要一直指向目的字符串的串尾,才能保证后面把源串连接过来。
2、接着通过一个循环,找到了目的字符串的串尾,即以\0结尾的位置。这个也提醒我们,如果要执行字符串连接,以\0结尾很重要,否则会coredump。
3、将源字符串一个一个的copy了过来。并不是将源字符串直接连接到目的字符串的串尾。
结论
到这里,就比较清楚的看出来,strcat其实是把源字符串复制到目的字符串的串尾来实现“连接”的功能。