该方案是将文件读入无符号char缓冲区,将该缓冲区放入istringstream中,并对其进行迭代。

istringstream data((char*)buffer);

char line[1024]
while (data.good()) {
     data.getline(line, 1024);

     [...]
}

if (
    data.rdstate() & (ios_base::badbit | ios_base::failbit)
) throw foobarException (

最初是被捕获的foobarException,它并没有说太多,因为这是一种不太可能的情况-文件是/proc/stat,缓冲区很好,并且实际上仅以此方式迭代了前几行,然后其余的的数据被丢弃(并且中断了循环)。实际上,该子句的从未被ijt_rstrong触发过。1

我要强调的一点是,仅使用了前几行,以及在调试等方面。缓冲区在发生故障之前显然仍然有大量数据,因此没有任何问题可以影响到EOF。

我逐步通过调试器检查了缓冲区是否已从文件中正确填充,并且getline()的每次迭代都得到了应有的状态,直到失败的神秘点为止-尽管由于这是一个致命错误,所以没有多少错误届时将获得更多信息。然后,我更改了上面的代码以捕获并更详细地报告错误:
istringstream data((char*)buffer);
data.exceptions(istringstream::failbit | istringstream::badbit);

char line[1024];
while (data.good()) {
    try { data.getline(line, 1024); }
    catch (istringstream::failure& ex) {

突然间事情发生了变化-该过程不是通过捕获和报告错误,而是通过try
中的SIGABRT 来死。回溯看起来像这样:

#0  0x00007ffff6b2fa28 in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/unix/sysv/linux/raise.c:55
#1  0x00007ffff6b3162a in __GI_abort () at abort.c:89
#2  0x00007ffff7464add in __gnu_cxx::__verbose_terminate_handler ()
    at ../../../../libstdc++-v3/libsupc++/vterminate.cc:95
#3  0x00007ffff7462936 in __cxxabiv1::__terminate (handler=<optimized out>)
    at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:47
#4  0x00007ffff7462981 in std::terminate ()
    at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:57
#5  0x00007ffff7462b99 in __cxxabiv1::__cxa_throw (obj=obj@entry=0x6801a0,
    tinfo=0x7ffff7749740 <typeinfo for std::ios_base::failure>,
    dest=0x7ffff7472890 <std::ios_base::failure::~failure()>)
    at ../../../../libstdc++-v3/libsupc++/eh_throw.cc:87
#6  0x00007ffff748b9a6 in std::__throw_ios_failure (
    __s=__s@entry=0x7ffff7512427 "basic_ios::clear")
    at ../../../../../libstdc++-v3/src/c++11/functexcept.cc:126
#7  0x00007ffff74c938a in std::basic_ios<char, std::char_traits<char> >::clear
    (this=<optimized out>, __state=<optimized out>)
---Type <return> to continue, or q <return> to quit---
    at /usr/src/debug/gcc-5.3.1-20160406/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_ios.tcc:48
#8  0x00007ffff747a74f in std::basic_ios<char, std::char_traits<char> >::setstate (__state=<optimized out>, this=<optimized out>)
    at /usr/src/debug/gcc-5.3.1-20160406/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_ios.h:158
#9  std::istream::getline (this=0x7fffffffcd80, __s=0x7fffffffcd7f "",
    __n=1024, __delim=<optimized out>)
    at ../../../../../libstdc++-v3/src/c++98/istream.cc:106
#10 0x000000000041225a in SSMlinuxMetrics::cpuModule::getLevels (this=0x67e040)
    at cpuModule.cpp:179
cpuModule.cpp:179try { data.getline(line, 1024) }

根据以下几个问题:
  • When does a process get SIGABRT (signal 6)?
  • What causes a SIGABRT fault?

  • 听起来这里确实只有两种可能性:
  • 我已经超出某个范围并破坏了istringstream实例。
  • 库中有一个错误。

  • 由于2似乎不太可能,并且我找不到#1的情况-例如,以valgrind运行,因此中止之前没有错误:

    ==8886== Memcheck, a memory error detector
    ==8886== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
    ==8886== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
    ==8886== Command: ./monitor_demo
    ==8886==
    terminate called after throwing an instance of 'std::ios_base::failure'
      what():  basic_ios::clear
    ==8886==
    ==8886== Process terminating with default action of signal 6 (SIGABRT)
    ==8886==    at 0x5D89A28: raise (raise.c:55)
    ==8886==    by 0x5D8B629: abort (abort.c:89)
    

    而且(当然)“到目前为止,它一直工作良好”,我很沮丧。

    除了斜视代码并尝试隔离路径,直到发现问题或让SSCCE演示错误为止,我是否不知道有什么可能提供快速解决方案?

    1.这个项目是一个不完整的项目,几个月后我又回来了,在此期间,我知道glibc已在系统上升级。

    最佳答案

    我相信奇怪的猜想是因为libc升级引入的ABI兼容性是正确的。系统已经运行了8天,并且在此期间进行了更新。

    重新启动后,并且没有更改代码的,它可以编译并运行而没有错误。我也在另一个系统上进行了测试,结果相同。

    可能的道理是,如果您发现glibc已更新,请重新启动系统...

    07-24 19:04
    查看更多