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

时间:2017-04-07 15:30:36

标签: c argv execv

我的程序有一个可变数量的args,我需要创建一个带有新路径的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 编辑2:我正在做find的版本,因此strcat会将当前目录添加到要查看的文件夹中。 这是目录的初始化: char *directory = strcat(argv[1],"/");

3 个答案:

答案 0 :(得分:2)

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

为此,请再分配一个元素,然后将其显式设置为NULL

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

假设argv通过main()传递,则此行

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

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

顺便说一句;请注意directory只是指针char,所以它不提供任何内存来存储任何&#34;字符串&#34;类似的值。

你可能想要什么而不是

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

...

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

是这样的(这假设argv[1]包含任何&#34; base&#34; -directorie的名称,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);

答案 1 :(得分:2)

您没有显示directory的设置方式。我怀疑它就像

char *directory = argv[1];

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

答案 2 :(得分:2)

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

修改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()