将 argv 复制到另一个变量以更改它而不更改原始变量

Copy argv to another variable to change it without change the original

我的程序有可变数量的参数,我需要用新路径创建一个 execv,所以我想在另一个变量中更改 argv[1] 的值而不更改它,但它不会让我。

char** arg_exec = malloc(argc * sizeof (char*));
int i;
for(i=0;i <= argc-1; i++)
   arg_exec[i] = strdup(argv[i]);
arg_exec[argc] = NULL;
if( (pid = fork()) == 0){
    arg_exec[1] = strcat(directory , dir_info->d_name); //some variables with the current path and a name
    execv(arg_exec[0], arg_exec);
    printf("Error in process %d\n", getpid());
    return 1;
 }

但是在 运行 之后,这一行 arg_exec[1] = strcat(directory , dir_info->d_name); 它改变了我的 argv[1] 值,我的程序失败了..

它与 execl 一起工作得很好,因为它就像 execl(argv[0],strcat(directory , dir_info->d_name), ..., NULL); 但是因为我有可变数量的参数给 运行 它,实现它并不好方式。

Edit1:在数组末尾添加了 NULL Edit2:我正在做 find 的一个版本,因此 strcat 将向当前目录添加一个要查看的文件夹。 这是目录的初始化: char *directory = strcat(argv[1],"/");

显示的代码未NULL-终止目标指针数组arg_exec

为此再分配一个元素,然后将其明确设置为 NULL


此外,代码对 arg_exe 的元素进行的第二次赋值会覆盖第一次的结果,导致内存泄漏,因为 strdup() 分配的内存地址丢失了。


假设 argv 通过 main() 传入,那么这一行

char *directory = strcat(argv[1],"/");

尝试将 "/" 连接到 argv[1] 指向的内容,并由此写入超出 argv[1] 的范围,并通过这样做调用未定义的行为。从那时起,任何事情都可能发生,从崩溃到似乎可以工作。

顺便说一句;请注意 directory 只是指向 char 指针 ,因此它不提供任何内存来存储任何类似 "string" 的值。

你可能想要什么而不是

char *directory = strcat(argv[1],"/");

...

  arg_exec[1] = strcat(directory , dir_info->d_name); 

是这样的(这假设 argv[1] 持有任何 "base"-目录的名称并且 argv_exe 是根据您的(更正的)代码分配和初始化的:

{
  void * tmp = realloc(arg_exec[1], 
    strlen(arg_exec[1]) + strlen("/") + strlen(dir_info->d_name) + 1);
  if (NULL == tmp)
  {
    perror("realloc() failed");
    exit(1);
  }

  arg_exec[1] = tmp;
}

strcat(arg_exec[1], "/");
strcat(arg_exec[1], dir_info->d_name);

您没有说明 directory 是如何设置的。我怀疑它类似于

char *directory = argv[1];

在这种情况下,strcat 将修改 directory 指向的位置,从而修改 argv。

char *directory = strcat(argv[1],"/"); 尝试修改 argv[1] 超出其分配,即 UB。 .

修改argv本身可能是UB。 Is argv[n] writable?

所以为两者分配内存。

注意:char** arg_exec = malloc(argc * sizeof (char*)); 不够,因为 argv[argc] 必须是 NULL。还需要1个。注意 argc 没有传递给 execv().


步骤 1. 复制指针数组 argv[]

char **argv_new;
size_t a_size = sizeof *argv_new * (argc + 1);  // + 1 for the final NULL
argv_new = malloc(a_size);
memcpy(argv_new, argv, a_size);

步骤 2. 形成新的 arg[1]

int size = 1 + snprintf(NULL, 0, "%s/%s", argv[1], dir_info->d_name);
argv_new[1] = malloc(size);
snprintf(argv_new[1], size, "%s/%s", argv[1], dir_info->d_name);

使用它

execv(arg_new[0], arg_new);
free(argv_new[1]);
free(argv_new);

待定:检查要添加的错误:argc > 1, malloc(), snprintf(), execv()