0

我的函数被传递了一个结构,其中包含一个以 NULL 结尾的指针数组,这些指针指向组成带有参数的命令的单词。

我正在对参数列表执行全局匹配,以将它们扩展为完整的文件列表,然后我想用新的扩展参数数组替换传递的参数数组。

globbing 工作正常,即 g.gl_pathv 填充了预期文件的列表。但是,我无法将此数组复制到给定的结构中。

#include <glob.h>

struct command {
  char **argv;
  // other fields...
}

void myFunction( struct command * cmd )
{
  char **p = cmd->argv;
  char* program = *p++; // save the program name (e.g 'ls', and increment to the first argument

  glob_t g;
  memset(&g, 0, sizeof(g));
  g.gl_offs = 1;
  int res = glob(*p++, GLOB_DOOFFS, NULL, &g);
  glob_handle_res(res);
  while (*p)
  {
      res = glob(*p, GLOB_DOOFFS | GLOB_APPEND, NULL, &g);
      glob_handle_res(res);
  }

  if( g.gl_pathc <= 0 )
  {
      globfree(&g);
  }

  cmd->argv = malloc((g.gl_pathc + g.gl_offs) * sizeof *cmd->argv);

  if (cmd->argv == NULL) { sys_fatal_error("pattern_expand: malloc failed\n");}
   // copy over the arguments
  size_t i = g.gl_offs;
  for (; i < g.gl_pathc + g.gl_offs; ++i)
      cmd->argv[i] = strdup(g.gl_pathv[i]);

  // insert the original program name
  cmd->argv[0] = strdup(program);
  ** cmd->argv[g.gl_pathc + g.gl_offs] = 0; **
  globfree(&g);
}

void 
command_free(struct esh_command * cmd)
{
    char ** p = cmd->argv;
    while (*p) {
        free(*p++); // Segfaults here, was it already freed?
    }
    free(cmd->argv);
    free(cmd);
}

编辑 1:另外,我意识到我需要将程序作为 cmd->argv[0] 粘贴到那里
编辑 2:添加对 calloc 的调用
编辑 3:使用 Alok
编辑 4 的提示编辑内存管理:来自 alok
编辑 5 的更多提示:几乎工作..释放命令结构时应用程序段错误

最后:好像我错过了终止 NULL,所以添加以下行:

cmd->argv[g.gl_pathc + g.gl_offs] = 0;  

似乎使它工作。

4

2 回答 2

1

argv是 的指针数组char *。这意味着argv有价值的空间argc char *。如果您尝试将多个char *值复制到其中,您最终会出现溢出。

您的调用很可能会glob导致字段中的多个argc元素gl_pathv(即gl_pathc > argc)。这是未定义的行为。

它类似于下面的代码:

/* Wrong code */
#include <string.h>

int a[] = { 1, 2, 3 };
int b[] = { 1, 2, 3, 4 };
memcpy(a, b, sizeof b);

解决方案:您应该glob_t直接使用结构,或者分配新空间以复制gl_pathv到新的char **

char **paths = malloc(g.gl_pathc * sizeof *paths);
if (paths == NULL) { /* handle error */ }
for (size_t i=0; i < g.gl_pathc; ++i) {
    /* The following just copies the pointer */
    paths[i] = g.gl_pathv[i];

    /* If you actually want to copy the string, then
       you need to malloc again here.

       Something like:

       paths[i] = malloc(strlen(g.gl_pathv[i] + 1));

       followed by strcpy.
     */
}

/* free all the allocated data when done */

编辑:编辑后:

cmd->argv = calloc(g.gl_pathc, sizeof(char *) *g.gl_pathc);

它应该可以工作,但是每个argv[1]toargv[g.gl_pathc + g.gl_offs - 1]都是char *struct glob. 您的memcpy电话只是复制指针。当您稍后执行时globfree(),这些指针不再具有任何意义。因此,您需要复制字符串以供使用:

size_t i;
cmd->argv = malloc((g.gl_pathc+g.gl_offs) * sizeof *cmd->argv);
for (i=g.gl_offs; i < g.gl_pathc + g.gl_offs; ++i)
    cmd->argv[i] = strdup(g.gl_pathv[i]);

这确保您现在拥有自己的私有字符串副本。完成后一定要释放它们(和argv)。

您的代码还有一些其他问题。

  1. 你正在做*p++,你应该做p++,因为你没有使用解引用的值。
  2. 你真的应该检查glob.
  3. 您的paths变量需要g.gl_pathc + 1元素,而不是g.gl_pathc. (或者更准确地说,您需要分配g.gl_pathc + g.gl_offstimessizeof *paths字节。)
  4. for复制字符串的循环应该是for (j=1; j < g.gl_pathc + g.gl_offs; ++j).
  5. 确保防止 shell 扩展你的 glob。即,调用./a.out '*'而不是./a.out *.
于 2010-03-15T01:37:33.710 回答
0

你不需要通过 sizeof(char *) 来多重 g.gl_pathc 吗?

于 2010-03-15T01:22:09.540 回答