与memcpy连接

时间:2011-08-03 18:15:20

标签: c string memcpy

我正在尝试使用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++;
}

3 个答案:

答案 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()的结果的方式检查和处理)。