【问题标题】:Can I use boost library for crossplatform application executing?我可以使用 boost 库来执行跨平台应用程序吗?
【发布时间】:2010-05-27 18:34:06
【问题描述】:

boost (c++) 库中是否有任何 WinAPI WinExec 模拟?我需要从我的程序运行可执行文件,并将参数传递给它。我应该为此使用任何其他跨平台库,还是自己处理我的程序编译的操作系统?

【问题讨论】:

  • 感谢您的回答,我停止了 spawnl() 函数,因为我需要非阻塞执行。

标签: c++ boost cross-platform


【解决方案1】:

重要提示:请参阅最后的 POSIX 系统更新。

我的意见是你应该使用你希望支持的各种平台提供的 API/系统调用,或者使用某种抽象层(Noah Roberts 提到的 Boost.Process 库可能是一个想法)来避免处理特定于平台的细节。

我强烈反对使用system 函数,因为它不打算启动您指定的进程,而是应该将您指定的字符串传递给“系统默认shell”或“命令处理器”(如果任何)。这有几个缺点:

  • 资源浪费;现在(通常)不是一个进程,而是生成两个进程,其中一个(外壳)对您的最终目标(启动您想要的进程)没有用处。这通常可以忽略不计,但在进程不是轻量级对象 (Windows) 的系统上,如果它们的资源不足,则可能会很明显。
  • 无用的混乱;每次未知/不受信任的进程启动新进程时,我处理过的几个安全套件都会发出警告;而不是仅仅显示警告,现在安全套件将显示其中两个(而您让第一个非常不清楚);
  • 结果的不可预测性;与平台无关的system 的文档可以用“未定义的行为”替换而不会造成太大损失——实际上是it is quite like that。我为什么这么说?因为:
    • 首先,甚至不能保证system 在当前平台上具有某种意义,因为根本没有“默认外壳”。但这是一个极端情况,通常不是问题——而且也很容易被抓住(if(system(NULL)==0) 没有外壳);真正的问题是
    • 一般来说,您不知道 什么 shell 是“默认 shell”,以及它如何解析其输入;在 Linux 上它通常是/bin/sh 更新:实际上,这是 POSIX 规定的,见下文,在 Windows 上它可能是 command.comcmd.exe ,在另一个操作系统上它仍然是另一回事。因此,您不确定,例如,如何转义路径中的空格,或者是否应该引用路径;哎呀,你甚至不知道这样的 shell 是否需要一些特殊的命令来启动可执行文件!
    • 更有趣:你甚至不知道调用是否真的阻塞了:你知道当system返回时,shell将被终止,但你不知道shell是否会等待生成的过程结束;具体示例:cmd.exe 不会在返回之前等待 GUI 可执行文件结束,而在 Linux 上,GUI 可执行文件与所有其他可执行文件一样是可执行文件,并且没有这种特殊处理。在这种情况下,您必须为 Windows 创建一个特殊情况,并创建一个类似 @987654323@ /wait youexecutable.exe 的命令字符串 - 希望解释器的版本仍然(或仍然,取决于 Windows 的版本)支持该语法。而 IIRC start 在 Windows 9x 和 Windows NT 系列上有不同的选项,所以你甚至不确定。
    • 这还不够:您甚至不确定应用程序是否已启动:system 返回值与命令解释器返回码相关。就system 而言,如果shell 启动,则调用成功,system 认为的错误就结束了。
    • 那么你就会得到 shell 的错误代码 - 再说一次,我们对此一无所知。也许它是最后执行命令的错误代码的副本;也许它只是一个相对于 shell 的错误代码(例如,1 = 执行的最后一个命令,0 = 最后一个命令无效),也许是 42。谁知道呢?

因为在一个好的应用程序中,您至少需要知道调用是阻塞还是非阻塞,获取有意义的退出代码(由您启动的应用程序实际返回的退出代码),确定应用程序是否已经开始,有有意义的错误代码以防出现问题,system 很可能不适合您的需求;要获得任何这些保证,您必须使用特定于平台的 hack 或无保证的假设,从而浪费了 system 的所有跨平台“兼容性”。

所以,我再说一遍:使用各种平台提供的系统调用(例如,POSIX 上的fork+exec,Windows 上的CreateProcess),它们准确地指定了它们保证做什么,或者使用第三方抽象代码; system的方式肯定不好。


更新:因为当我写这个答案时,我了解到在 POSIX 系统上 system is specified way better - 特别是,它被强制执行命令使用/bin/sh -c command,阻塞直到shell进程终止。

sh 行为,反过来,is mandated in several ways by POSIX;因此,在 POSIX 系统上,“结果的不可预测性”下列出的一些缺点不再适用:

  • 指定了默认的 shell,所以,只要你只使用 POSIX 保证的 sh 东西(例如,没有 bashisms),你就安全了;
  • 调用阻塞;
  • 如果你的命令格式正确,shell本身不会遇到问题,waitpid成功,...,你应该get a copy of the error code of the executed program

因此,如果您在 POSIX 上运行,情况就不会那么悲惨了;相反,如果您必须便携,请继续避免使用system

【讨论】:

    【解决方案2】:

    system() 有什么问题,它是标准 C++ 的一部分?见http://www.cplusplus.com/reference/clibrary/cstdlib/system

    【讨论】:

    • 谢谢。这是合适的。我没有太多的编程实践,所以问这些愚蠢的问题。
    • 仍然应该避免使用系统,因为它会无缘无故地生成一个新的 shell,不提供有用的错误代码,而且它的行为通常不太可预测(它完全取决于生成的 shell) .
    • @Matteo 创建一个新的 shell 是好事还是坏事是有争议的(实际上 C++ 和 C 标准并没有说这必须发生 - 有些平台可能没有“shell” ),但 system() 是执行另一个可执行文件的唯一标准方法 - popen 和 exec/spawn 函数并非在所有平台上都可用。
    • @Matteo 这里有一个叫做“答案”的东西。请将您的咆哮发布为一个。
    • 好的,把整个咆哮转移到一个答案上。 :)
    【解决方案3】:

    我认为有一个库正在尝试进入 boost,名为 Boost.Process。你必须找到它的下载,可能在沙盒或其他东西中。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-07-10
        • 1970-01-01
        • 2011-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多