我正在尝试使用memcpy将两个字符串添加到一起。第一个memcpy包含我需要的数据。然而,第二个没有增加。知道为什么吗?
if (strlen(g->db_cmd) < MAX_DB_CMDS )
{
memcpy(&g->db_cmd[strlen(g->db_cmd)],l->db.param_value.val,strlen(l->db.param_value.val));
memcpy(&g->db_cmd[strlen(g->db_cmd)],l->del_const,strlen(l->del_const));
g->cmd_ctr++;
}
答案 0 :(得分:7)
size_t len = strlen(l->db.param_value.val);
memcpy(g->db_cmd, l->db.param_value.val, len);
memcpy(g->db_cmd + len, l->del_const, strlen(l->del_cost)+1);
这可以获得以下结果:
strlen
的冗余调用。每个都必须遍历字符串,因此最好尽量减少这些调用。memcpy
需要实际附加,而不是替换。所以第一个参数必须与之前的调用不同。+1
的第3个arg中的memcpy
。那是NUL终结者。我不确定你的if
陈述是否有意义。也许更明智的做法是确保g->db_cmd
有足够的空间来复制你的内容。您可以通过sizeof
(如果db_cmd
是一个字符数组)或跟踪堆分配的大小(如果通过db_cmd
获取malloc
)来实现。所以也许最有意义的是:
size_t param_value_len = strlen(l->db.param_value.val),
del_const_len = strlen(l->del_const);
// Assumption is that db_cmd is a char array and hence sizeof(db_cmd) makes sense.
// If db_cmd is a heap allocation, replace the sizeof() with how many bytes you
// asked malloc for.
//
if (param_value_len + del_const_len < sizeof(g->db_cmd))
{
memcpy(g->db_cmd, l->db.param_value.val, param_value_len);
memcpy(g->db_cmd + param_value_len, l->del_const, del_const_len + 1);
}
else
{
// TODO: your buffer is not big enough. handle that.
}
答案 1 :(得分:1)
你没有复制空终止符,你只是处理原始字符串数据。这会使您的字符串非空终止,这可能会导致各种问题。您也没有检查以确保缓冲区中有足够的空间,这可能导致buffer overflow vulnerabilities。
要确保复制空终止符,只需将1复制为要复制的字节数 - 复制strlen(l->db.param_value.val) + 1
个字节。
答案 2 :(得分:1)
一个可能的问题是,您的第一个memcpy()
调用不一定会导致空终止字符串,因为您没有从l->db.param_value.val
复制'\ 0'终结符:
因此,当在strlen(g->db_cmd)
的第二次调用中调用memcpy()
时,它可能会返回一些完全虚假的东西。这是否是一个问题取决于g->db_cmd
缓冲区是否事先初始化为零。
为什么不使用strcat()
,这是为了与memcpy()
完全相同?
if (strlen(g->db_cmd) < MAX_DB_CMDS )
{
strcat( g->db_cmd, l->db.param_value.val);
strcat( g->db_cmd, l->del_const);
g->cmd_ctr++;
}
这样可以让人更容易阅读。你可能会认为性能较差 - 但我不这么认为,因为你明确地进行了一堆strlen()
次调用。在任何情况下,我都会集中精力先把它弄好,然后再担心性能。不正确的代码就像你可以得到的那样没有优化 - 在快速获得它之前做到正确。事实上,我的下一步不是提高代码性能,而是改进代码以减少缓冲区溢出(我可能会转而使用类似strlcat()
的代码strcat()
)。
例如,如果g->db_cmd
是char数组(而不是指针),结果可能如下所示:
size_t orig_len = strlen(g->db_cmd);
size_t result = strlcat( g->db_cmd, l->db.param_value.val, sizeof(g->db_cmd));
result = strlcat( g->db_cmd, l->del_const, sizeof(g->db_cmd));
g->cmd_ctr++;
if (result >= sizeof(g->db_cmd)) {
// the new stuff didn't fit, 'roll back' to what we started with
g->db_cmd[orig_len] = '\0';
g->cmd_ctr--;
}
如果strlcat()
不属于您的平台,则可以很容易地在网上找到它。如果您正在使用MSVC,则可以使用strcat_s()
函数代替(但请注意,它不等同于strlcat()
- 您必须更改调用strcat_s()
的结果的方式检查和处理)。