Важно : см. Обновление в конце для систем 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
.