Сбой программы при вызове execvp для компиляции программы с ошибкой? - PullRequest
0 голосов
/ 26 ноября 2018

Я использую execvp для компиляции программы с ошибкой.Но затем на экране моего терминала появляется сообщение об ошибке, которое не должно произойти, потому что если execvp завершится ошибкой, он только позволит дочернему элементу вернуться со статусом выхода.Я не понимаю, почему мой терминал на самом деле отображает сообщение об ошибке?

Мой массив команд: {gcc, studentcode.c, ourtest3.c, -o, ourtest3.x, NULL} и в ourtest3.c,Я сделал несколько ошибок специально.Моя вызывающая функция выглядит так:

commands = {"gcc", "studentcode.c", "ourtest3.c", "-o", "ourtest3.x", NULL};
int compile_program(Char** commands) {
  pid_t pid;
  int status;

  pid = safe_fork();
    if (pid == 0) { /*Child*/
      if (execvp(commands[0], commands) < 0) {
    exit(0);
      }
    } else { /*Parent*/
      if (wait(&status) == -1) {
    return 0;
      }
      if (WIFEXITED(status)) {
    if (WEXITSTATUS(status) != 0) {
      return 1;
    }
      } else {
    return 0;
      }
    }
  return 1;
}

ourtest3.c таков:

#include <stdio.h>
#include <assert.h>
#include "studentcode.h"

int main(void) {
  assert(product(2, 16) == 32

  printf("The student code in public07.studentcode.c works on its ");
  printf("third test!\n");

  return 0;
}

Моя программа должна была нормально завершиться с возвращаемым значением 0, но вместо этого в моем окне терминала,это показывает, что

ourtest3.c: In function 'main':
ourtest3.c:19:0: error: unterminated argument list invoking macro "assert"
ourtest3.c:13:3: error: 'assert' undeclared (first use in this function)
ourtest3.c:13:3: note: each undeclared identifier is reported only once for each function it appears in
ourtest3.c:13:3: error: expected ';' at end of input
ourtest3.c:13:3: error: expected declaration or statement at end of input

1 Ответ

0 голосов
/ 26 ноября 2018

Если вы хотите изменить stdin, stout и stderr процесса, вам нужно это сделать.В противном случае он просто наследует их от своего родителя.После fork и до execvp вы, вероятно, захотите open /dev/null и dup передать его по файловым дескрипторам 0 и 1.

Вот некоторый некрасивый код без проверки ошибок:

if (pid == 0) { /*Child*/

  /* Redirect stdin and stderr to /dev/null */
  int fd = open ("/dev/null", O_RDONLY);
  dup2(STDIN_FILENO, fd);
  dup2(STDERR_FILENO, fd);
  close(fd);

  if (execvp(commands[0], commands) < 0) {
_exit(0);
  }

Вы также можете перенаправить их в файлы или каналы, если хотите, чтобы родитель имел доступ к выходным данным дочернего элемента.

Обратите внимание на вызов _exit.Не имейте привычку звонить exit от детей-неудачников.Это вызвало ошибки с серьезными последствиями для безопасности в прошлом.Представьте, что у вашего процесса есть что-то, что он собирается делать, когда он exit s (например, сброс буфера в терминал или сетевое соединение).Позвонив exit в ребенка, вы делаете эту вещь дважды .Вы можете подумать, что знаете, что у вас нет такой вещи, но вы не можете этого знать (в общем), потому что вы не представляете, что ваши библиотеки могут делать внутри.

...