在c ++中使用popen调用cli实用程序崩溃。在shell或fork,exec等中工作正常

时间:2016-05-12 09:22:15

标签: c++ linux

我面临一个奇怪的问题。我编写了一个命令行实用程序,它调用第三方库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调用。即使我从守护进程调用包装器shell脚本,它仍然会崩溃。我不理解被执行的进程与其父进程的关系,它可能导致崩溃。我知道api正试图用空指针创建一个字符串,但是,令我感到困惑的是,当我直接从命令行或我编写的一个简单的c ++程序调用cli时,它不会发生。操作系统是linux。 要调试,我试过

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

1 个答案:

答案 0 :(得分:0)

我弄清楚问题是什么。第三方库试图访问未定义的环境变量。库代码没有处理这个并且崩溃了。问题出在第三方图书馆,他们同意修复。 为了他人的利益,我通过上面提到的大量调试发现了这一点。最后我对环境持怀疑态度。所以我用这样的“env -i”来运行cli,

<?php
    $num = $con->query("SELECT gcm_regid from gcm_users")->rowCount();
    $current_num = 0;
    $message = $_POST["message"];
    for ($i = 0; $i < $num / 999; $i++) {
        $query = $con->query("SELECT gcm_regid from gcm_users LIMIT $current_num, 999");
        foreach ($query as $data) {
            $row[] = $data["gcm_regid"];
        }
        $pushStatus = send_notification($con, $row, $message);
        $current_num += 999;
    }
?>

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