【问题标题】:Using execvp with bounded char *将 execvp 与有界字符一起使用 *
【发布时间】:2014-03-02 22:15:54
【问题描述】:

我有:

char * tokens[50][2];  

在此设置中,tokens[i][0] 指向参数的开头,tokens[i][1] 指向结尾。这些标记不是空终止的。要打印它们,我正在使用:

printf("%.*s ",(int)(com->tokens[i][1] - com->tokens[i][0] + 1), com->tokens[i][0]); 

现在我需要使用它们来执行一个功能。我正在尝试使用 execvp 完成这项工作。如果可能的话,我会尽量避免为这些字符串分配内存。有没有办法将有界字符串作为参数发送?有什么想法吗?

【问题讨论】:

    标签: c pointers exec


    【解决方案1】:

    由于execvp() 仅适用于以空字符结尾的字符串,因此您要么必须以空字符结尾的字符串,要么……实际上,没有 or 选项,因为所有系统调用都使用空字符终止的字符串。

    好的:另一种方法是制作以 null 结尾的字符串副本并使用副本调用 execvp()。由于您知道它们有多长,因此您将能够相当有效地执行此操作 - 但您需要分配足够的内存。

    size_t req_size = 0;
    for (int i = 0; i < n; i++)
        req_size += (com->tokens[i][1] - com->tokens[i][0] + 2);
    char **argv = malloc((n + 1) * sizeof(argv[0]));
    char *args = malloc(req_size);
    if (argv == 0 || args == 0)
        …report memory allocation failure; do not continue…
    char *argp = args;
    int i;
    for (i = 0; i < n; i++)
    {
        size_t len_i = com->tokens[i][1] - com->tokens[i][0] + 1;
        argv[i] = argp;
        memmove(argv[i], com->tokens[i][0], len_i);
        argv[i][len_i] = '\0';
        argp += len_i + 1;
    }
    assert(argp == args + req_size);
    argv[i] = 0;                      // Null terminate list of pointers
    
    execvp(argv[0], argv);
    

    嵌入 SSCCE 的代码 (Short, Self-Contained, Correct Example):

    #include <assert.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct command
    {
        int n;
        char *tokens[50][2];
    };
    
    static void print_fixed(struct command *com)
    {
        printf("fixed:\n");
        printf("%d:", com->n);
        for (int i = 0; i < com->n; i++)
            printf(" [%.*s]", (int)(com->tokens[i][1] - com->tokens[i][0] + 1), com->tokens[i][0]);
        putchar('\n');
    }
    
    static void print_argv(int argc, char **argv)
    {
        printf("argv:\n");
        for (int i = 0; i <= argc; i++)
        {
            char *arg = argv[i];
            if (arg == 0)
                arg = "<<NULL pointer>>";
            printf("%d: [%s]\n", i, arg);
        }
    }
    
    int main(void)
    {
        char data[] = "command arg1 arg2 arg3 arg4";
        struct command cmd =
        {
            5,
            { { &data[ 0], &data[ 6] }, { &data[ 8], &data[11] },
              { &data[13], &data[16] }, { &data[18], &data[21] },
              { &data[23], &data[26] },
            }
        };
        struct command *com = &cmd;
        int n = com->n;
        print_fixed(com);
    
        size_t req_size = 0;
        for (int i = 0; i < n; i++)
            req_size += (com->tokens[i][1] - com->tokens[i][0] + 2);
        char **argv = malloc((n + 1) * sizeof(argv[0]));
        char *args = malloc(req_size);
        if (argv == 0 || args == 0)
        {
            fprintf(stderr, "Memory allocation failure\n");
            exit(1);
        }
        char *argp = args;
        int i;
        for (i = 0; i < n; i++)
        {
            size_t len_i = com->tokens[i][1] - com->tokens[i][0] + 1;
            argv[i] = argp;
            memmove(argv[i], com->tokens[i][0], len_i);
            argv[i][len_i] = '\0';
            argp += len_i + 1;
        }
        assert(argp == args + req_size);
        argv[i] = 0;                      // Null terminate list of pointers
    
        print_argv(i, argv);
    
        return 0;
    }
    

    输出:

    fixed:
    5: [command] [arg1] [arg2] [arg3] [arg4]
    argv:
    0: [command]
    1: [arg1]
    2: [arg2]
    3: [arg3]
    4: [arg4]
    5: [<<NULL pointer>>]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-12
      • 1970-01-01
      • 1970-01-01
      • 2021-06-06
      • 1970-01-01
      • 2016-04-24
      • 2013-12-22
      • 1970-01-01
      相关资源
      最近更新 更多