在程序运行时编译程序

Cem*_*mre 16 c++ runtime compilation

我有一个广泛的问题:

假设我有一个C++程序,我开始在后台运行一个文件,其中一些配置可以在内部设置.在它运行时,我更改了这些内部配置,编译它并开始在另一个文件上运行它.

这是否会影响之前已在后台运行的实例?或者因为它已经启动并运行它不会?对此有任何想法表示赞赏.

jle*_*ahy 19

修改正在运行的可执行文件是不安全的.根据覆盖内存映射可执行文件时会发生什么?

在Linux下,如果在运行时替换可执行文件,结果将无法预测,并且可能会崩溃.

如果删除该文件并编译该程序的新版本,那么将会定义的内容非常明确.已经运行的实例将使用前面的代码,操作系统将在内存中保存,直到程序终止.任何新实例都将使用新代码.

摘要:您应该确保您的构建系统在重新编译之前删除旧的可执行文件,并且只要这是真的,那么重新编译将在您重新运行程序之后生效,否则行为是未定义的(读取SIGSEGV).

各种附录:

JamesKanze正确地指出链接器本身可能在写入其输出之前删除该文件,如果是这种情况,那么它将始终表现得就像您在重新编译之前自己删除了文件一样(理智的场景).从binutils cvs head 看bfd/cache.c:

/* Create the file.

   Some operating systems won't let us overwrite a running
   binary.  For them, we want to unlink the file first.

   However, gcc 2.95 will create temporary files using
   O_EXCL and tight permissions to prevent other users from
   substituting other .o files during the compilation.  gcc
   will then tell the assembler to use the newly created
   file as an output file.  If we unlink the file here, we
   open a brief window when another user could still
   substitute a file.

   So we unlink the output file if and only if it has
   non-zero size.  */
Run Code Online (Sandbox Code Playgroud)

所以至少在GNU LD中,这可以保证很好.然而,这并不一定延伸到其他连接器.

  • 这取决于链接器如何创建其输出文件.如果它只是执行`open`,截断现有文件,那么正在运行的可执行文件如果需要在任何代码中进行分页,则会出现一些意外情况.但是,如果链接器在打开新文件之前删除该文件,则运行程序应该不受影响. (3认同)

edA*_*a-y 6

可能/将要发生什么取决于操作系统,但一般来说,旧程序永远不会开始运行新代码.我说这是依赖操作系统的,因为在Windows上我认为文件将被锁定而你根本无法覆盖它,而在Linux上,你必须取消链接旧文件,但程序仍将使用旧版本,而你的新版本在技术上将是一个不同的文件.

现在有一个警告.如果您有动态库或其他动态代码资源,那么您可能会获得新版本.在任何情况下,您根据需要加载库,您加载的版本将是加载时存在的版本.在大多数情况下,所有库都在程序开始时直接加载.然而,它们不是插件体系结构的一种常见情况是根据需要加载它们.