代码之家  ›  专栏  ›  技术社区  ›  R Samuel Klatchko

exec如何改变exec'ed程序的行为

  •  7
  • R Samuel Klatchko  · 技术社区  · 14 年前

    我正试图追查一次非常奇怪的车祸。奇怪的是有人发现了一个解决方法,我无法解释。

    解决方法是这个小程序,我将其称为“运行程序”:

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    
    int main(int argc, char *argv[])
    {
        if (argc == 1)
        {
            fprintf(stderr, "Usage: %s prog [args ...]\n", argv[0]);
            return 1;
        }
    
        execvp(argv[1], argv + 1);
    
        fprintf(stderr, "execv failed: %s\n", strerror(errno));
    
        // If exec returns because the program is not found or we
        // don't have the appropriate permission
        return 255;
    }
    

    正如你所看到的,这个程序所做的只是使用 execvp 用另一个程序替换自己。

    当直接从命令行调用程序时,程序崩溃:

    /path/to/prog args  # this crashes
    

    但当它通过我的运行程序垫片间接调用时,工作正常:

    /path/to/runner /path/to/prog args   # works successfully
    

    在我的生活中,我可以理解拥有一个额外的exec如何改变正在运行的程序的行为(正如您所看到的那样,程序不会改变环境)。

    关于车祸的一些背景。崩溃本身在C++运行时中发生。具体来说,当程序执行 throw ,崩溃版本错误地认为没有匹配的catch(尽管有)和调用 terminate . 当我通过runner调用程序时,异常被正确捕获。

    我的问题是,为什么额外的exec会改变exec'ed程序的行为?

    5 回复  |  直到 14 年前
        1
  •  3
  •   Mark B    14 年前

    运行程序加载的.so文件可能导致runee正常工作。尝试对每个二进制文件进行ldd'ing,看看是否有库正在加载不同的版本/位置。

        2
  •  1
  •   baol    14 年前

    可能被调用的程序有内存泄漏。尝试使用Valgrind或其他内存检查工具运行它。在发生内存错误之后,其他的一切都是未定义的行为(因此一切都可能发生)。

        3
  •  0
  •   Thomas Pornin    14 年前

    黑暗中的一个场景:双执行可能会改变RAM中环境变量的顺序。

    环境是带有指针的内存结构;内核将该结构复制到新进程的地址空间中。在复制过程中,RAM中元素的实际顺序可能会改变(环境变量不是语义顺序,但RAM中的地址有顺序)。使用两个exec(),可以修改订单两次。

    RAM中字符串顺序的改变会发现一个bug,这有点奇怪,但发生了一些奇怪的事情。

        4
  •  0
  •   MarkR    14 年前

    我想知道你是否传递了不同的argv[0]到什么是shell。很明显,我看不到您上面写的内容,但是您可能将argv[0]设置为程序的实际第一个参数,而shell将其设置为其调用的名称(例如完整路径或短路径)。

        5
  •  0
  •   Douglas Leeder    14 年前

    我想有两件事你可以比较“工作”和“崩溃”版本-打开文件描述符和信号处理程序-因为这些都是由exec传递的。

    我看不出问题是什么/有什么不同,但也许有必要消除它们。