我试图追踪一个非常奇怪的崩溃。奇怪的是,有人发现了一种我无法解释的解决方法。
解决方法是这个小程序,我将其称为“跑步者”:
#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
。当我通过跑步者调用程序时,异常被正确捕获。
我的问题是,为什么额外的exec改变了exec'ed程序的行为?
答案 0 :(得分:3)
跑步者加载的.so文件可能导致runee正常工作。尝试ldd'ing每个二进制文件,看看是否有任何库加载不同的版本/位置。
答案 1 :(得分:1)
也许被调用的程序有内存泄漏。尝试使用valgrind或其他一些内存检查工具运行它。在您遇到内存错误之后,其他所有内容都是未定义的行为(因此一切都会发生)。
答案 2 :(得分:0)
在黑暗中拍摄:双执行可能会改变RAM中环境变量的顺序。
环境是一个带指针的内存结构;内核将该结构复制到新进程的地址空间中。 RAM中元素的实际顺序可能会在该复制期间发生变化(环境变量不是语义排序的,但RAM中的地址有顺序)。使用两个exec(),订单可能会被修改两次。
RAM中字符串排序的变化发现了一个bug有些怪异,但是发生了一些奇怪的事情。
答案 3 :(得分:0)
我想知道你是否将argv [0]中的不同内容传递给shell。我无法从上面的内容中看到,但是你可能将argv [0]设置为程序的实际第一个参数,而shell则将其设置为其被调用的名称(例如,完整或短路径) )
答案 4 :(得分:0)
我猜你可以在'working'和'crashing'版本之间比较两件事 - 打开文件描述符和信号处理程序 - 因为它们会被exec传递。
我看不出它们是怎样的问题/不同,但可能值得消除它们。