在c++中使用popen调用cli实用程序时崩溃.适用于shell或fork、exec等

cli utility crashing while invoked using popen in c++. Works fine in shell or fork, exec etc

本文关键字:shell 适用于 崩溃 fork exec 实用程序 c++ popen cli 调用      更新时间:2023-10-16

我面临一个奇怪的问题。我编写了一个命令行实用程序,它调用第三方库api来完成第三方设备的一些管理任务。我已经彻底测试了这个实用程序,它运行良好。我有自己的守护进程(用c++编写),它根据收到的请求,使用popen调用这个命令行实用程序。如果我这样做,该实用程序会在库api中崩溃,给出类似的错误

terminate called after throwing an instance of 
'std::logic_error' what(): basic_string::_S_construct null not valid

我的cli实用程序调用方式如下

./cli --host hostname --command cmd --other otheropts etc etc.

它是使用c++字符串从守护进程调用的,守护进程根据收到的请求构建参数。它最终像这样调用我的cli

setenv("LOGIN", login_.c_str(), 1);
setenv("PASSWORD", password_.c_str(), 1);
std::string complete = cli_path_ + " ";
complete += formatString("--host %s --command ", host_);
complete += cmd;
complete += " 2>&1"; // get stderr as well
FILE *f = popen(complete.c_str(), "r");

然后读取生成的文件指针并解析输出。崩溃只发生在从守护进程调用时,而不是从shell调用时。即使我从守护进程调用了一个包装外壳脚本,它仍然会崩溃。我不了解execed进程与其父进程的关系,它可能会导致崩溃。我知道在某个地方,api试图用空指针创建一个字符串,然而,让我困惑的是,当我直接从命令行或我编写的一个简单的c++程序中调用cli时,这不会发生。操作系统是linux。为了调试,我尝试了

  1. 使用fork和exec而不是popen调用它。(崩溃)
  2. 调用调用此cli的shell脚本。(崩溃)
  3. 直接调用,如上所示。(作品)
  4. 使用c++简单程序作为包装器从shell调用(有效)
  5. 介入gdb直到第三方api。(从守护进程调用时api崩溃)

我发现了问题所在。第三方库试图访问未定义的环境变量。库代码无法处理此问题并崩溃。所以问题出在第三方图书馆,他们已经同意修复。为了其他人的利益,我通过如上所述的大量调试发现了这一点。最后我对环境产生了怀疑。所以我用这样的"env-I"运行cli,

env -i ./cli --args <args>

其清除环境变量。它坠毁了!。然后,我通过对运行cli时设置的所有环境变量进行二进制搜索,找出了哪个环境变量。