【问题标题】:How can I send command line arguments to a malloc array, and then send those arguments from a parent process to a child process如何将命令行参数发送到 malloc 数组,然后将这些参数从父进程发送到子进程
【发布时间】:2019-05-30 21:06:19
【问题描述】:

这是一个学校作业,我知道这是一个简单的问题,但对于我的生活,我无法弄清楚我做错了什么。

在父进程中,我需要将 cmdline 参数转换为整数,然后将参数存储在 malloc 数组中。然后我需要一次将每个整数发送给子进程。然后子进程将对从父进程传递的所有整数求和。求和完成后,会将总和返回给父进程。然后父进程打印出总和。

关于这段代码,我有 3 件事不明白。

  1. 获取命令行参数,将它们转换为整数,并使用指向malloc 数组的指针存储它们。我不明白为什么我不能在我的父进程中写这个:
  int* numArray = (int*) malloc (argc * sizeof(int));
  for(int i = 0; i < argc; ++i){
     numArray[i] = atoi(argv[i+1]);
  }
  1. 如何将单个值发送到子进程进行求和?我可以一次读取它们,然后将 sum 增加 sumBuf 中的值。然后sumBuf 被下一个值覆盖,并将 sum 再次增加sumBuf。我该怎么做?

  2. 如何在父进程中访问子进程的返回值?

将整数存储在malloc 数组中会产生分段错误,我不明白如何纠正这个错误。还有,既然fork返回的是孩子的PID,那么如果孩子返回一个sum,那么sum不应该是孩子的PID吗?

  1. 对于 malloc 数组,我尝试在 for 循环中取消引用 numArray,例如:
   *numArray[i] = atoi(argv[i+1]) 
  1. 我已尝试在 for 循环中将单个值写入管道

  2. 我知道fork返回的是child的PID值,那么如果child返回sum,不应该sum=p,把sum存入parent的sum值吗?

    int main(int argc, char **argv){
      int *numArray = (int*) malloc (argc * sizeof(int));
      pid_t p;
      int fd[2];
      pipe(fd);
      p = fork()
      //error checks
    
      if(p == 0){//child process
           int sum = 0;
           int sumBuf = 0;
           close(fd[1]);//close write end
           for(int i = 0; i < argc; ++i){
               read(fd[0], sumBuf, sizeof(int));
               sum += sumBuf;
           }
           close(fd[0]);//close read end
           return sum;//return sum from child process
       }
       else{//parent process
           int sum = 0;
           close(fd[0]);//close read end
           for(int i = 0; i < argc; ++i){
               numArray[i] = atoi(argv[i+1]);
               write(fd[1], numArray[i], sizeof(int));
           }
           close(fd[1]);//close write end of pipe
           sum = p;
           printf("Sum = %d", sum);
           return 0;
       }
       free(numArray);
       return 0;
    }
    

当我尝试运行此程序时,我收到一条分段错误消息。请不要说我笨,我明白要做什么的想法,但我不明白如何实现它..

【问题讨论】:

  • 如果i == argc -1,那么argv[i+1]是什么?
  • 当您致电atoi(argv[argc]) 时,您预计会发生什么?

标签: c


【解决方案1】:

在进入主要内容之前……我假设您已将#include &lt;stdlib.h&gt;(以及&lt;stdio.h&gt;&lt;unistd.h&gt;)放在那里。

这个:

int *numArray = (int*) malloc (argc * sizeof(int));

可以用更好的替代品代替:

int *numArray = malloc(argc * sizeof *numArray);

演员表是不必要的。此外,使用sizeof *pointer 更好,如果你需要 要更改数组指向的数据类型,您无需更改 sizeof。此外,如果您忘记#include &lt;stdlib.h&gt;malloc() 将返回一个int。放置演员表基本上告诉编译器对此保持沉默。如果您不放置演员表,您将收到一条诊断消息。

作为一个好习惯,最好检查一下返回值 malloc(),例如

if (!numArray) {
    return EXIT_FAILURE;
}

另外,strtol()atoi() 更好,因为前者提供了错误检查。

Nitpick:您需要在fork() 之后放置;

如果你需要将一个值从孩子传回给父母,你不能做什么 你做到了:sum = p;。相反,您应该创建另一个管道,如果操作 系统不支持双向管道(假设这一点可能更安全)。一世 将此作为练习留给您。

现在,write()read() 需要它们的第二个参数一个指针。因此对于 例如,read() 应该是:

read(fd[0], &sumBuf, sizeof sumBuf);

write() 也是如此。

我不明白你为什么不能只写 malloc() 在 父进程。你当然可以,而且像孩子一样好,像我一样 理解,应该无权访问分配的内存。

现在,段错误最可能的原因是未定义的行为 读取过去的数组绑定。在这种情况下,argv。这可能更容易 举例说明:

如果你这样运行:

./a.out 1 2 3

argc 将是 4,这意味着您只能访问 argv[0]argv[3]。现在, 这里有一个提示:看看循环。

【讨论】:

    【解决方案2】:
    1. 我不明白为什么我不能在我的父进程中写这个——这正是你所做的,它应该可以工作。没有什么问题。

    2. readwrite 函数将缓冲区的地址作为第二个参数。您已尝试传递变量的值。将以下行更改为 -

    read(fd[0], sumBuf, sizeof(int));
    

    read(fd[0], &sumBuf, sizeof(int));
    

    write(fd[1], numArray[i], sizeof(int));
    

    write(fd[1], &(numArray[i]), sizeof(int));
    

    这应该可以为您解决问题。此外,您的编译器一定已经警告过您这些。请将所有警告视为错误。

    1. 您可以通过查看fork 的返回值来访问父进程中的子进程ID。在您的情况下,变量p

    您似乎还混淆了 PID 和进程返回的值。 PID 是进程标识符。它是一个过程所独有的。返回值是该进程的主要函数返回的值。这可以是整数(两个进程也可以返回相同的值)。父级可以使用wait 函数访问其子级返回的值。

    【讨论】:

      猜你喜欢
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 2010-12-12
      • 2019-12-12
      • 1970-01-01
      • 1970-01-01
      • 2012-07-19
      相关资源
      最近更新 更多