在可执行文件运行时重新编译是否安全?

HC4*_*ica 27 linux windows executable recompile

如果我在运行时重新编译可执行文件会发生什么?操作系统在开始运行时是否将所有可执行文件的内容读入内存,因此它永远不会读取新的可执行文件?或者它会读取新的可执行文件的部分,认为它没有改变,导致可能未定义的行为?

如果我运行的脚本在循环中重复调用可执行文件,并且在脚本运行时重新编译可执行文件,该怎么办?是否保证循环的未来迭代将调用新的可执行文件,并且只有在进行切换时正在进行的调用的结果可能已损坏?

我的操作系统是Linux,但我也很好奇Windows上会发生什么.

Dav*_*ley 30

由于这是一个传统的编译器,它写出了一个可执行文件,让我们在Linux中使用它.

首先要知道的是Linux文件名不是直接引用文件,而是引用与文件名无关的目录条目.文件实际上不需要文件名,但如果不是,则很难引用它.

如果进程正在使用文件,并且您替换或删除它,则该进程将通过其目录条目继续使用该文件.使用该文件或查找它的任何新进程都将获得新版本(如果您替换它)或找不到它(如果您删除它).一旦所有进程都通过旧文件,它将从文件系统中删除.

因此,如果重新编译并创建同名的新可执行文件,则不会影响正在运行的进程.它将继续使用旧的可执行文件.尝试打开文件的任何新进程都将获得新进程.如果你已经进入system("foo");循环,那么每次执行它都会看到文件名foo的含义.

Windows以不同方式处理文件 通常,如果有使用文件的进程,则该文件被锁定,可能不会被删除或替换.


Chr*_*isF 8

这取决于.

如果操作系统将整个可执行文件读入内存并且没有返回磁盘映像,则可以在"正在使用"时重新编译它.

在实践中,这并不总是发生.如果操作系统在可执行文件上保持文件句柄打开(如Windows),则会阻止文件被删除和/或覆盖.

使用Linux/Unix,可以覆盖"正在使用"的文件.有关详细解释,请参阅David Thornley的答案.


lak*_*tak 6

在Windows中,您无法删除锁定的文件,但大多数人不知道的是您可以移动或重命名正在运行的exe文件.

所以你可以

  • 将旧的exe移动到同一驱动器上的临时目录
  • 安排在下次重启时删除:MoveFileEx(name,NULL,MOVEFILE_DELAY_UNTIL_REBOOT);
  • 移动一个新的exe代替它.

旧程序将继续运行,但新进程将使用新文件.

  • 有趣的信息可用于展示糟糕的设计选择可能导致奇怪的变通方法.通过将有关文件的信息拆分为,文件名和inode,不需要这样复杂的命令.此外,无需重启.升级可以即时进行. (4认同)

cam*_*amh 6

在Linux下,可执行文件需要按需分页到内存中。磁盘上的可执行文件将成为应用程序的后备存储。这意味着您无法修改磁盘上的可执行文件,否则将影响正在运行的应用程序。如果尝试open(2)使用正在使用的可执行文件进行写入,则会收到ETXTBSY(文本文件忙)错误(请查看手册页中的open(2))。

正如许多其他人所说的那样,您可以从文件系统(unlink(2))中删除文件,内核将维护对该文件的引用,直到不再有其他引用时才从磁盘中删除该文件(当进程退出时,它将释放对文件的引用)。文件)。这意味着您可以通过先删除正在使用的可执行文件,然后创建一个与旧文件同名的新文件来有效地“覆盖”正在使用的可执行文件。

因此,归结为“覆盖”现有文件时编译器如何创建可执行文件。如果它只是打开要写入的文件并将其截断(O_WRONLY|O_CREAT|O_TRUNC),则它将失败并显示ETXTBSY错误。如果它首先删除了现有的输出文件并创建了一个新文件,它将正常工作。