Могу ли я использовать библиотеку boost для выполнения кроссплатформенных приложений? - PullRequest
2 голосов
/ 27 мая 2010

Есть ли какой-нибудь WinAPI-аналог WinExec в библиотеках boost (c ++)? Мне нужно запустить исполняемый файл из моей программы и передать ему параметры. Должен ли я использовать для этого какие-либо другие кроссплатформенные библиотеки или решить, для какой ОС скомпилирована моя программа?

Ответы [ 4 ]

15 голосов
/ 28 мая 2010

Важно : см. Обновление в конце для систем POSIX.

Мое мнение таково, что вам следует использовать API / системные вызовы, предоставляемые различными платформами, которые вы хотите поддерживать, или использовать какой-либо уровень абстракции (библиотека Boost.Process , упомянутая Ноа Робертсом, может быть идеей), чтобы не иметь дело с деталями, специфичными для платформы.

Я категорически не согласен с использованием функции system, поскольку она не предназначена для запуска указанного вами процесса, а вместо этого она должна передавать указанную вами строку в «системную оболочку по умолчанию» или «командный процессор» (если любой). Это имеет несколько недостатков:

  • потеря ресурсов; вместо процесса сейчас (обычно) вы порождаете два, один из которых (оболочка) бесполезен для вашей конечной цели (запуска процесса, который вы хотите). Обычно это незначительно, но может быть заметно в системах, где процессы не являются легковесными объектами (Windows), если им не хватает ресурсов.
  • бесполезная путаница; несколько пакетов безопасности, с которыми я имел дело, предупреждают каждый раз, когда неизвестный / ненадежный процесс запускает новый процесс; вместо того, чтобы просто отображать предупреждение, теперь пакет безопасности отобразит два из них (а вы делаете первое совершенно неясным);
  • непредсказуемость результата; документация system, не зависящая от платформы, может быть заменена без особых потерь "неопределенным поведением" - и на самом деле это очень похоже на . Почему я это говорю? Так как:
    • Прежде всего, нет даже гарантии, что system имеет какое-то значение на текущей платформе, поскольку вообще не может быть "оболочки по умолчанию". Но это крайний случай, который обычно не является проблемой - и это также можно легко поймать (if(system(NULL)==0) нет оболочки); настоящая проблема в том, что
    • в общем, вы не имеете представления о , что shell является «оболочкой по умолчанию», и как она анализирует свои входные данные; в Linux это будет обычно /bin/sh обновление: на самом деле, это предписано POSIX, см. ниже , в Windows это может быть command.com, а также cmd.exe, в другая ОС это будет еще одна вещь. Таким образом, вы не уверены, например, как избежать пробелов в пути или если вы должны указать путь; черт возьми, вы даже не знаете, требует ли такая оболочка какой-либо специальной команды для запуска исполняемых файлов!
    • Более интересно: вы даже не знаете, блокирует ли вызов на самом деле: вы знаете, что к тому времени, когда system вернется, оболочка будет прервана, но вы не знаете, будет ли оболочка ждать появившегося процесс до конца; Конкретный пример: cmd.exe не ждет окончания выполнения исполняемых файлов GUI перед возвратом, в то время как в Linux исполняемые файлы GUI являются исполняемыми файлами, как и все другие, и не имеют такой специальной обработки. В этом случае вам придется создать специальный случай для Windows и создать командную строку, такую ​​как <a href="http://ss64.com/nt/start.html" rel="noreferrer" title="Start - Start a program">start</a> /wait youexecutable.exe - надеясь, что версия интерпретатора все еще (или все же, в зависимости от версии Windows) поддерживает этот синтаксис. И у IIRC start есть разные опции для Windows 9x и семейства Windows NT, так что вы даже не будете в этом уверены.
    • Этого недостаточно: вы даже не уверены, запущено ли приложение: возвращаемое значение system относится к интерпретатору команд , код возврата Что касается system, то, если оболочка запущена, вызов завершился успешно и там заканчивается то, что system считает ошибкой.
    • Тогда у вас остается код ошибки оболочки - о котором, опять же, мы ничего не знаем. Возможно, это точная копия кода ошибки последней выполненной команды; возможно, это код ошибки, относящийся только к оболочке (например, 1 = последняя выполненная команда, 0 = последняя команда была недействительной), может быть, это 42. Кто знает?

Поскольку в хорошем приложении вы хотите, по крайней мере, узнать, является ли вызов блокирующим / неблокирующим, получить значимый код выхода (тот, который фактически был возвращен приложением, которое вы запустили), чтобы убедиться, что приложение был запущен, чтобы иметь значимые коды ошибок на случай, если что-то пошло не так, system, скорее всего, не соответствует вашим потребностям; Чтобы получить какую-либо из этих гарантий, вы должны пойти на хаки для конкретной платформы или с негарантированными предположениями, тратя впустую всю кроссплатформенную «совместимость» system.

Итак, я скажу это снова: используйте системные вызовы, предоставляемые различными платформами (например, fork + exec в POSIX, CreateProcess в Windows), которые точно указывают, что они гарантированно делают, или идут с абстрагирующим кодом третьей стороны; путь system определенно не хорош.


Обновление : поскольку, когда я писал этот ответ, я узнал, что в системах POSIX system указан намного лучше - в частности, он обязывает он будет выполнять команды с /bin/sh -c command, блокируя до завершения процесса оболочки.

Поведение

sh, в свою очередь, предписывается несколькими способами POSIX ; таким образом, в системах POSIX некоторые недостатки, перечисленные в разделе «непредсказуемость результата», больше не применяются:

  • указана оболочка по умолчанию, поэтому, пока вы используете только sh материал, гарантированный POSIX (например, без bash isms), вы в безопасности;
  • вызов является блокировкой;
  • если ваша команда правильно сформирована, сама оболочка не сталкивается с проблемами, waitpid succedes, ..., вам следует получить копию кода ошибки выполненной программы

Итак, если вы работаете в POSIX, ситуация будет менее трагичной; если вместо этого вы должны быть портативным, продолжайте избегать system.

4 голосов
/ 27 мая 2010

Что не так с system(), который является частью стандарта C ++? Смотри http://www.cplusplus.com/reference/clibrary/cstdlib/system.

1 голос
/ 27 мая 2010

Есть библиотека, которая, как я полагаю, пытается получить импульс, называется Boost.Process. Вам нужно будет найти загрузку для него, вероятно, в песочнице или еще много чего.

0 голосов
/ 27 мая 2010

Возможно, вы захотите взглянуть на этот вопрос относительно popen () на win32: popen

...