glibc wordexp WRDE_REUSE是如何实现内存复用的?

新手上路,请多包涵

关于glibc wordexp 接口的实现,有一处不太明白,请教大神。

接口如下:

int wordexp (const char *words, wordexp_t *pwordexp, int flags)

看了一下glibc的实现,当flag为WRDE_REUSE时,会先释放pwordexp,然后再调用calloc重新申请内存,这种操作时如何做到复用pwordexp原来的内存的?

代码段如下:

int
wordexp (const char *words, wordexp_t *pwordexp, int flags)
{
  size_t words_offset;
  size_t word_length;
  size_t max_length;
  char *word = w_newword (&word_length, &max_length);
  int error;
  char *ifs;
  char ifs_white[4];
  wordexp_t old_word = *pwordexp;
  if (flags & WRDE_REUSE) /*** 这里会释放pwordexp->we_wordv  ***/
    {
      /* Minimal implementation of WRDE_REUSE for now */
      wordfree (pwordexp);
      old_word.we_wordv = NULL;
    }
  if ((flags & WRDE_APPEND) == 0)
    {
      pwordexp->we_wordc = 0;
      if (flags & WRDE_DOOFFS)
        {
          pwordexp->we_wordv = calloc (1 + pwordexp->we_offs, sizeof (char *));
          if (pwordexp->we_wordv == NULL)
            {
              error = WRDE_NOSPACE;
              goto do_error;
            }
        }
      else
        {
          pwordexp->we_wordv = calloc (1, sizeof (char *)); /*** 此处调用calloc重新为we_wordv申请内存 ***/
          if (pwordexp->we_wordv == NULL)
            {
              error = WRDE_NOSPACE;
              goto do_error;
            }
          pwordexp->we_offs = 0;
        }
    }

wordfree的实现源码如下:

void
wordfree (wordexp_t *pwordexp)
{
  /* wordexp can set pwordexp to NULL */
  if (pwordexp && pwordexp->we_wordv)
    {
      char **wordv = pwordexp->we_wordv;
      for (wordv += pwordexp->we_offs; *wordv; ++wordv)
        free (*wordv);
      free (pwordexp->we_wordv);
      pwordexp->we_wordv = NULL;
    }
}

flags枚举:

enum
  {
    WRDE_DOOFFS = (1 << 0),     /* Insert PWORDEXP->we_offs NULLs.  */
    WRDE_APPEND = (1 << 1),     /* Append to results of a previous call.  */
    WRDE_NOCMD = (1 << 2),      /* Don't do command substitution.  */
    WRDE_REUSE = (1 << 3),      /* Reuse storage in PWORDEXP.  */
    WRDE_SHOWERR = (1 << 4),    /* Don't redirect stderr to /dev/null.  */
    WRDE_UNDEF = (1 << 5),      /* Error for expanding undefined variables.  */
    __WRDE_FLAGS = (WRDE_DOOFFS | WRDE_APPEND | WRDE_NOCMD |
                    WRDE_REUSE | WRDE_SHOWERR | WRDE_UNDEF)
  };

完整源码:https://code.woboq.org/usersp...

阅读 1.8k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进