【问题标题】:Error when dealing with memory - mremap_chunk: Assertion处理内存时出错 - mremap_chunk: Assertion
【发布时间】:2011-12-14 03:30:00
【问题描述】:

这似乎是我以前的帖子,但这里的问题不同..

这是问题的 C 结构 -

typedef struct ip_esp_private {         /* keep track of things privately */
u_int32_t type;        
u_int32_t ivlen;       
u_int32_t icvlen;      
u_int32_t keylen;       /* length of "Encryption key */
u_int32_t akeylen;      /*length of authn key */
u_int32_t key[0];       /* encryption key and authentication key both */

} esp_private; 

这些值在运行时提供给结构内容,如下所示 -

  case 'k':       /* Key */
            length = stringargument(arg, &temp);
            priv->keylen = length;


            priv = (esp_private *)realloc(priv,
                            sizeof(esp_private)+/*length*/priv->keylen); 
             /*This one is edited */


        //  if(priv->akeylen)       
          //        memmove(&priv->key[priv->keylen],
                 //                    &priv->key[0],priv->akeylen);
   /*These three are commented*/     

       memcpy(&priv->key[0], temp, priv->keylen);
            pack->private = priv;
             pack->modified |= ESP_MOD_KEY;
            break;



    case 'K':       /* Authentication  Key */  
            length = stringargument(arg, &temp);
            priv->akeylen = length; // marked line(explained below)

            priv = (esp_private *)realloc(priv,
                            sizeof(esp_private)+/*length*/priv->keylen+priv->akeylen);
           /*this one edited too */ 


           memcpy(&priv->key[priv->keylen/sizeof(u_int32_t)],
                                             temp,priv->akeylen);
            pack->private = priv;
            pack->modified |= ESP_MOD_KEY;

现在有一个使用身份验证密钥值的函数。

函数的相关部分是-

    if (!epriv->akeylen) {
            key = &fakekey;
            keylen = 1;
    } else {
            key = (u_int8_t *)malloc(epriv->akeylen);
            memcpy(key,&epriv->key[epriv->keylen/sizeof(u_int32_t)]
                             ,epriv->akeylen);

现在,当我尝试运行以下程序时,遇到了这个我不知道的错误。

     sendip: malloc.c:3574: mremap_chunk: Assertion `((size + offset)
                                  & (mp_.pagesize-1)) == 0' failed.

我认为功能部分可能有错误,但我不确定它到底是什么, 因为当我评论标记的行(如上所述)时,akeylen 为空 所以采用fakekey 值和程序运行良好。

编辑 1:

我已经在三个地方编辑了代码(在上面的代码中也进行了编辑)。

现在程序可以运行,但输出不一致。

输入:

 Encryption key - qwerty

 Authentication key - abcdef

输出:

  Encryption key - qwerab

  Authentication key - abcdef

现在情况更清楚了。

这意味着realloc 声明中肯定存在问题。

请就此提出建议。

最初我在两个realloc 语句中都添加了长度,但现在我将其更改为priv->keylen 在第一位置和priv->keylen+priv->akeylen 在第二位置。

但是还有一些地方需要改进

为什么要覆盖???

【问题讨论】:

  • 这纯属猜测,但你知道stringargument(arg, &temp) 的结果是什么吗?看起来您的realloc 调用正在升级为mmap 调用(或mremap),当您请求分配非常大的大小时会发生这种情况。如果您的 stringargument 函数偶然返回了一些太大的垃圾值,那么可能会发生有趣的事情。
  • 请看看我的编辑
  • 好的,我看到你的编辑了。但是你需要澄清你现在所看到的。你看到同样的断言失败了吗?或者您没有看到断言,但现在您正在覆盖一些内存?还是两者都见过?
  • 现在没有错误了。我已经在上面显示了输入和输出,请查看密钥,加密密钥正在被身份验证密钥覆盖
  • 为什么 VLA key[0] 是 uint32_t ?它似乎仅用作字符数组。此外,如果 keylen 不是 u_int32_t 的倍数,您尝试使用“&epriv->key[epriv->keylen/sizeof(u_int32_t)]”的字符串连接将覆盖内容。

标签: c memory-management memcpy memmove


【解决方案1】:

由于 key[0] struct hack 似乎包含两个键的空间,因此您也需要为这两个键分配内存。在这两种情况下('k' 和 'K')

priv = realloc(priv, sizeof *priv +priv->keylen+priv->akeylen);

当连接两个键时,最简单的方法是将 u_int32_t 键转换为字符指针并对其进行算术运算:

memcpy ( priv->key, source1, sizeofsource1);
/* and */ 
memcpy ( ((char*) priv->key) +priv->keylen, source2, sizeofsource2);

[与 memmove() 类似] 可以删除程序中的其余演员表。

【讨论】:

    【解决方案2】:

    如果您从 inin malloc 得到断言失败,则问题出在外部。断言不是关于传递给 malloc 的参数,而是关于已损坏的内存状态。这意味着您之前写入了您不应该写入的内存区域。因此,即使您提供了正确的回溯(例如使用 gdb),也不会指出问题的根源。有许多用于调试内存问题的工具。使用最广泛的工具之一是 valgrind。它会让你的程序变得非常慢,并通过查看每一个内存访问来向你展示大量可能的问题。另一个更轻量级的工具是挡泥板,它是用来链接的。缩小问题范围的一个非常基本的方法是将assert(condition) 语句添加到您的代码中,并希望您早点失败。有时您可以通过查看代码中的每一个内存访问并确保它没有超出范围来解决这个问题(或者如果您不确定,请添加断言语句)。

    【讨论】:

      猜你喜欢
      • 2011-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-15
      • 1970-01-01
      • 2017-06-29
      • 2014-11-12
      • 2012-07-05
      相关资源
      最近更新 更多