我可以为跨平台应用程序执行使用boost库吗?

3

Boost (C++)库中是否有任何类似于WinAPI WinExec的功能?我需要从我的程序中运行可执行文件,并向其传递参数。我应该使用其他跨平台库来处理这个问题,还是自己处理编译程序所需的操作系统?


感谢您的回答,我选择了spawnl()函数,因为我需要非阻塞执行。 - Heisenberg
4个回答

16
重要提示:有关POSIX系统的更新,请参见文章结尾。
我的观点是,您应该使用各个平台提供的API /系统调用,或者使用某种抽象层(Noah Roberts提到的Boost.Process库可能是一个好主意),以避免处理特定于平台的细节。
我强烈反对使用system函数,因为它不是用于启动您指定的进程,而是应将您指定的字符串传递给“系统默认shell”或“命令处理器”(如果有)。这有几个缺点:
  • 资源浪费; 现在你生成了两个进程,其中一个 (shell) 对你的最终目标 (启动你想要的进程) 是无用的。这通常可以忽略不计,但在进程不是轻量级对象的系统上 (Windows),如果资源占用过多,可能会引起注意。
  • 无用的混乱; 我处理过的几个安全套件每次都会警告每当一个未知/不受信任的进程启动新进程时;现在安全套件将显示两个警告(并且你使第一个警告变得非常不清楚)而不是只显示一个警告;
  • 结果的不可预测性; 平台无关的system的文档可以被替换为 "未定义行为" 而没有太大的损失 - 实际上 就是这样。为什么这么说?因为:
    • 首先,在当前平台上甚至没有保证 system 具有某种意义,因为根本没有 "默认 shell"。但这是一个极端情况,通常不是问题 - 也很容易解决 (if(system(NULL)==0) 就没有 shell);真正的问题是
    • 一般来说,你不知道"默认 shell"是什么,以及它如何解析输入;在 Linux 上,它通常将是 /bin/sh 更新:实际上,这是 POSIX 强制执行的,请参见下文,在 Windows 上,它可能是 command.com 以及 cmd.exe,在其他操作系统上,它仍然是其他内容。因此,您不确定例如应该如何转义路径中的空格,或者是否应该引用路径;好吧,您甚至不知道这样的 shell 是否需要某些特殊命令才能启动可执行文件!
    • 更有趣的是:您甚至不知道调用是否阻塞:您知道到 system 返回 shell 将被终止,但您不知道 shell 是否等待出现的进程结束;具体例子:在 Windows 上,cmd.exe 在返回之前不会等待 GUI 可执行文件结束,而在 Linux 上,GUI 可执行文件与其他所有可执行文件一样运行,不会接受特殊处理。在这种情况下,您必须为 Windows 创建一个特殊情况,并创建一个命令字符串,例如:start /wait youexecutable.exe - 希望解释器版本仍然(或尚未,取决于 Windows 版本)支持该语法。我IRC start 在 Windows 9x 和 Windows NT 家族上有不同的选项,因此您甚至不能确定那个。
    • 还不够:您甚至不确定应用程序是否已启动: system 的返回值相对于命令解释器的返回代码。就 system 而言,如果启动了 shell 则调用成功,这是 system 认为的错误的结束。
    • 然后,你只剩下 shell 的错误代码 - 关于此,我们再次一无所知。也许它是最后一个执行的命令的错误代码的复印件;也许它是与 shell 相关的错误代码(例如,1 = 最后执行的命令,0 = 上一个命令无效),也许它是 42.谁知道?
在一个好的应用程序中,您至少需要知道调用是阻塞还是非阻塞,以获得有意义的退出代码(实际由启动的应用程序返回的代码),确保应用程序已启动,在出现问题时具有有意义的错误代码。因此,system 很可能不适合您的需求;要获得任何这些保证,您必须使用特定于平台的技巧或非保证假设,浪费了所有跨平台的“兼容性”。所以,我再次声明:请使用各个平台提供的系统调用(例如,在 POSIX 上是 fork+exec,在 Windows 上是 CreateProcess),它们会明确指定它们保证的内容,或者使用第三方抽象代码;system 的方式绝对不好。
更新:自从我写这篇答案以来,我了解到在POSIX系统上,system的规定要好得多-特别是,它被指定为将使用/bin/sh -c command执行命令,并阻塞直到shell进程终止。

sh行为,反过来由POSIX的几种方式规定;因此,在POSIX系统上,“结果不可预测”下列出的一些缺点不再适用:

  • 默认shell已指定,因此,只要您使用POSIX保证的sh内容(例如没有bash主义),您就是安全的;
  • 调用阻塞的;
  • 如果您的命令格式正确,shell本身不会遇到问题,waitpid成功,...,您应该获得已执行程序的错误代码副本

因此,如果您运行在POSIX上,则情况要少得多;如果您必须可移植,请继续避免使用system


4

谢谢。这很合适。我在编程方面没有太多的实践经验,所以问了一些愚蠢的问题。 - Heisenberg
然而,应该避免使用system函数,因为它会无缘无故地生成一个新的shell,不提供有用的错误代码,并且其行为通常不太可预测(完全取决于生成的shell)。 - Matteo Italia
@Matteo 无论创建一个新的 shell 是否是好事还是坏事都是有争议的(实际上,C++ 和 C 标准并没有规定必须这样做——某些平台可能没有“shell”),但 system() 是执行另一个可执行文件的唯一标准方法——popen 和 exec/spawn 函数并不适用于所有平台。 - anon
1
@Matteo 这里有个东西叫做“答案”。请把你的怒气发泄写成一个答案。 - anon
好的,把整个发言转移到答案中。 :) - Matteo Italia
链接已过期。 - jaques-sam

1

有一个我认为正在尝试进入Boost的库叫做Boost.Process。你需要找到它的下载链接,可能在沙盒或其他地方。


0

你可能想看一下关于win32上popen()的这个问题:popen


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接