有没有一种直接的方法来复制C中的argv?

时间:2014-01-09 21:11:22

标签: c

在C中编写小型UNIX实用程序时,我有时希望获取提供给main()的argv副本,以便在调用exec()之前调整参数。以下内容基于BSD的xargs(1)的实现:

void run_script(char *argv[]) {
    char **tmp, **new_argv;
    int argc;

    for (argc=0; argv[argc] != 0; argc++);
    new_argv = malloc((argc + 1) * sizeof(char *));
    for (tmp=new_argv; *argv != 0; tmp++) {
        *tmp = *argv++;
        *tmp = strdup(*tmp);
    }

    /* call execvp(3) using new_argv */

    for (i=0; i<=argc; i++)
            free(new_argv[i]);
    free(new_argv);
}

这感觉比它需要的更复杂。有没有更好的方法在C中写这个? (也许填写使用_POSIX_ARG_MAX分配的单个缓冲区。)

2 个答案:

答案 0 :(得分:1)

我的C有点生疏,但是......

假设argv []在脚本的持续时间内可用,如果不打算更改字符串,则无需删除字符串。分配内存后(如果要添加额外的参数,请记住要向argc添加更多内容),您应该能够memcpy。你的new_argv将指向与原始argv相同的字符串,因此在更改之前需要进行strdup(如果你想将其设置为其他字符串则不需要)。

我认为你需要密切关注你的循环,for (m=0, tmp.. - 首先,我不认为m会在其他任何地方使用;第二,你正在测试*argv != 0,但是没有在循环中更改* argv,所以它将永远运行或根本不运行,第三,在这个循环开始时,所有new_argv都是空指针,所以{{ 1}}会尝试复制内存地址为0的字符串,与argv无关。

答案 1 :(得分:1)

我想出了另一个复制argv的过程。以下示例不短,但我认为更容易阅读:

void run_script(char *argv[]) {
    int i;
    char **new_argv;
    char *p, *arg_buf;
    int argc;

    for (argc=0; argv[argc]; argc++);
    arg_buf = malloc(ARG_MAX);
    new_argv = calloc(argc+1, sizeof(char *));
    for (i=0, p=arg_buf; i<argc; i++) {
            p += strlcpy(p, argv[i], ARG_MAX - (p - arg_buf));
            p++;
    }

    /* call execvp(3) using new_argv */

    free(arg_buf);
    free(new_argv);
}

在Linux上ARG_MAX应替换为sysconf(_SC_ARG_MAX)