How does glibc wordexp WRDE_REUSE achieve memory reuse?

there is one thing I don"t quite understand about the implementation of the glibc wordexp interface.

API is as follows:

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

take a look at the implementation of glibc. When flag is WRDE_REUSE, pwordexp, will be released first and then calloc will be called to re-apply for memory. How to reuse the original memory of pwordexp in this operation?

the code snippet is as follows:

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 *)); /*** callocwe_wordv ***/
          if (pwordexp->we_wordv == NULL)
            {
              error = WRDE_NOSPACE;
              goto do_error;
            }
          pwordexp->we_offs = 0;
        }
    }
The source code of

wordfree is as follows:

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; PPwordv)
        free (*wordv);
      free (pwordexp->we_wordv);
      pwordexp->we_wordv = NULL;
    }
}

flags enumeration:

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)
  };

complete source code: https://code.woboq.org/usersp.

C
Sep.16,2021
Menu