首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >与memcpy连接

与memcpy连接
EN

Stack Overflow用户
提问于 2011-08-04 02:15:20
回答 3查看 8.2K关注 0票数 4

我正在尝试使用memcpy将两个字符串添加到一起。我需要,第一个memcpy确实包含数据。然而,第二个没有添加。知道为什么吗?

代码语言:javascript
复制
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++;
}
EN

回答 3

Stack Overflow用户

发布于 2011-08-04 02:28:05

代码语言:javascript
复制
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实际上需要追加,而不是替换。所以第一个参数必须不同于之前的调用,注意第二个memcpy的第三个参数中的+1。这是给NUL终结者的。

我也不确定您的if语句是否有意义。也许更明智的做法是确保g->db_cmd有足够的空间来存储您将要复制的内容。您可以通过sizeof (如果db_cmd是一个字符数组)或通过跟踪堆分配的大小(如果db_cmd是通过malloc获得的)来实现。因此,也许它最有意义的原因是:

代码语言:javascript
复制
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.
}
票数 7
EN

Stack Overflow用户

发布于 2011-08-04 02:24:28

您不是在复制null终止符,您只是在复制原始字符串数据。这使得您的字符串不能以null结尾,这可能会导致各种问题。您也没有检查以确保缓冲区中有足够的空间,这可能会导致buffer overflow vulnerabilities

为了确保复制空终止符,只需在要复制的字节数上加1 --复制strlen(l->db.param_value.val) + 1字节。

票数 1
EN

Stack Overflow用户

发布于 2011-08-04 02:26:02

一个可能的问题是,由于您没有从l->db.param_value.val复制'\0‘终止符,所以第一个memcpy()调用不一定会导致以null结尾的字符串

因此,当在第二次调用memcpy()时调用strlen(g->db_cmd)时,它可能会返回一些完全虚假的东西。这是否是一个问题取决于是否事先将g->db_cmd缓冲区初始化为零。

为什么不使用strcat(),它就是用来做您想要用memcpy()做的事情的

代码语言:javascript
复制
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是一个字符数组(而不是指针),则结果可能如下所示:

代码语言:javascript
复制
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()的结果的方式)。

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

https://stackoverflow.com/questions/6931193

复制
相关文章

相似问题

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