将输入流重定向到字符串时的c ++程序核心转储

时间:2015-09-08 01:42:41

标签: rhel c++

我最近发现我的c ++程序是在尝试从输入流重定向到字符串时在Red Hat Linux上的核心转储。程序提供PID并尝试从/ proc中获取进程名称。代码如下:

std::string processName;
std::stringstream filename;

filename << "/proc/" << pid << "/status";
std::ifstream f(filename.str().c_str());

if (f.good()) {
  std::string label;
  f >> label; // This causes the core dump

  if (label == "Name:") {
    f >> processName;
  }
}
f.close();

我做了一些搜索并发现了以下c ++错误,它看起来与我的问题非常相似(请注意最后一条评论,特别是我正在执行的操作)。 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53984

我已经能够使用一个小型测试程序在紧密循环中执行相同操作来重现问题,但仍然不太了解实际问题背后的原因。

有没有人意识到尝试使用上面显示的方法(在/ proc中)读取进程名称有任何问题?我正在考虑重写我的代码以使用系统调用而不是从文件系统中读取,但是在进行更改之前希望得到一些建议。

1 个答案:

答案 0 :(得分:0)

这是可以重现您的问题的代码:

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <cstdlib>
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>

int main(int argc, char **argv)
{
        pid_t pid = fork();
        if (!pid) {
                // Child process immediately dies and becomes a zombie
                exit(0);
        }

        std::string processName;
        std::stringstream filename;

        // Open status of child process dying
        filename << "/proc/" << pid << "/status";
        std::ifstream f(filename.str().c_str());

        // Wait for child process attaining death
        wait(NULL);

        // Read status of child process already gone
        if (f.good()) {
                std::string label;
                // This causes the core dump
                // read() returns ESRCH (No such process)
                f >> label;

                if (label == "Name:") {
                        f >> processName;
                }
                std::cout << processName << std::endl;
        }
        f.close();

        return 0;
}

strace -f ./a.out显示:

clone(Process 624 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f20758daa10) = 624
[pid   623] brk(0)                      = 0x8b8000
[pid   623] brk(0x8d9000)               = 0x8d9000
[pid   623] open("/proc/624/status", O_RDONLY <unfinished ...>
[pid   624] exit_group(0)               = ?
[pid   623] <... open resumed> )        = 3
[pid   623] wait4(-1,  <unfinished ...>
[pid   624] +++ exited with 0 +++
<... wait4 resumed> NULL, 0, NULL)      = 624
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=624, si_status=0, si_utime=0, si_stime=0} ---
read(3, 0x8b84b0, 8191)                 = -1 ESRCH (No such process)
write(2, "terminate called after throwing "..., 48terminate called after throwing an instance of ') = 48
write(2, "std::ios_base::failure", 22std::ios_base::failure)  = 22
write(2, "'\n", 2'
)                      = 2
write(2, "  what():  ", 11  what():  )             = 11
write(2, "basic_filebuf::underflow error r"..., 47basic_filebuf::underflow error reading the file) = 47
write(2, "\n", 1
)                       = 1
rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
gettid()                                = 623
tgkill(623, 623, SIGABRT)               = 0
--- SIGABRT {si_signo=SIGABRT, si_code=SI_TKILL, si_pid=623, si_uid=1000} ---
+++ killed by SIGABRT (core dumped) +++
Aborted (core dumped)

根本原因是内核在ESRCH上返回read()(没有这样的过程),这是libstdc ++意外的。我不确定在哪里责备,内核或用户名库。