【问题标题】:Parsing command line for execve() error. Plain C解析 execve() 错误的命令行。纯C
【发布时间】:2013-03-06 03:15:42
【问题描述】:

我是 C 指针的新手,我试图用命令行执行进程并获取它的 pid。任何使用命令行的 system()、sh() 等都不会返回 pid,所以我决定使用 execve()。但需要命令行解析为字符串数组。

我找到了一些现有的解决方案,但我无法使任何解决方案发挥作用。所以,我自己写了。它在我的测试程序中有效,但在实际程序中会导致分段错误。 谁能告诉我,我错在哪里? 代码是:

void cmdline_to_argv(const char* cmd_line, char*** argv, int* argc){
    int len, i, count, spc;
    char *s,*d;
    /* make a copy to play with */
    char *cmd_line1 = strdup(cmd_line);

    /* count items to deal with and trim multiple spaces */
    d = s = cmd_line1; spc = 1; count = 0; len=strlen(cmd_line1);
    for (i=0; i<len;i++,s++) {
        switch (*s) {
        case ' ':
            if (spc) continue;
            *d++ = '\0'; /* replace spaces with zeroes */
            spc = 1;
            break;
        default:
            if (spc) { count++; spc = 0; }
            *d++ = *s;
        }
    }
    (*d++) = '\0'; /* line termination */
    /* reallocate copy to correct size */
    cmd_line1 = realloc( cmd_line1, d - cmd_line1);
    /* allocate array of poiters */
    *argv = (char**) malloc(sizeof(char*) * (count+1));
    argv[count] = NULL;
    /* scan line again to find all lines starts and register */
    s = cmd_line1;
    for (i=0; i<count; i++) {
        (*argv)[i] = s;
        while (*(s++)) ;
    }
    *argc = count;
}

这就是我所说的:

char **chargv = NULL;
int chargc;

/* parse line to argument array */
cmdline_to_argv(cmdline, &chargv, &chargc);

我认为这里的所有问题都与我分配数组并写入它的指针操作有关。如何正确处理?

【问题讨论】:

    标签: c pointers segmentation-fault argv


    【解决方案1】:

    问题已结束。找到解决方案。棘手的指针声明语法解决了。这是有效的。

    感谢所有人。 :-|

     void cmdline_to_argv(const char* cmd_line, char ***argv, int* argc){
        int i, spc;
        size_t len;
        char *s,*d;
        /* make a copy to play with */
        char *cmd_line1 = strdup(cmd_line);
    
        /* count items to deal with and trim multiple spaces */
        d = s = cmd_line1; spc = 1; *argc = 0; len=strlen(cmd_line1);
        for (i=0; i<len;i++,s++) {
            switch (*s) {
            case ' ':
                if (spc) continue;
                *d++ = '\0'; /* replace spaces with zeroes */
                spc = 1;
                break;
            default:
                if (spc) { (*argc)++; spc = 0; }
                *d++ = *s;
            }
        }
        (*d++) = '\0'; /* line termination */
        /* calc actual size */
        len = d - cmd_line1;
        /* allocate array of poiters */
        *argv = (char**) malloc(sizeof(char*) * ((*argc)+1) + len);
        (*argv)[*argc] = (char*) NULL;
        d = (char*) &(*argv)[(*argc)+1];
        memmove(d, cmd_line1, len);
        free(cmd_line1);
        cmd_line1 = d;
        /* scan line again to find all lines starts and register */
        for (i=0; i<*argc; i++) {
            (*argv)[i] = d;
            while (*(d++)) ;
        }
    }
    
    /* deallocate array and strings */
    void free_argv(char ***argv) {
        free(*argv); /* strings laying together at once after pointers array */
    }
    

    【讨论】:

      【解决方案2】:

      你看过这里吗https://www.kernel.org/doc/man-pages/online/pages/man2/getpid.2.html 我相信你想要的是 getpid() 虽然也许你还有更多的要求。

      【讨论】:

      • 谢谢。但是 getpid() 仅在当前进程中有效,并且孩子不是我自己的,所以我不能在其中使用 getpid()。在启动子进程后,必须在父进程中知道子进程的 Pid。也许,在 system() 调用或类似的方法之后,还有另一种获取 pid 的方法,不需要数组而是单行?
      • 所以你在 fork 之后试图在父节点中获取子节点的 pid?如果你是那么 fork 将孩子的 pid 返回给父母。
      • 是的!我真的使用 fork() 来获取 pid,然后使用 execve() 调用用另一个进程映像覆盖分叉的孩子。这就是为什么我需要将行转换为 execve() 的数组。上面显示的转换程序是我的问题。它出现故障,我需要知道原因。
      猜你喜欢
      • 1970-01-01
      • 2017-09-08
      • 2011-03-03
      • 1970-01-01
      • 1970-01-01
      • 2013-11-18
      • 2016-08-07
      • 1970-01-01
      • 2023-03-21
      相关资源
      最近更新 更多