2016-05-23 3 views
1

Сценарий - это файл, который считывается в неподписанный буфер символов, буфер помещается в поток istringstream, а строки в нем повторяются.SIGABRT, вызванный через istringstream.getline()

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, буфер хорошо, и только первые несколько строк на самом деле повторяется таким образом, а остальные данные отбрасываются (и цикл прерывается). Фактически, этот пункт имеет никогда уволен ранее.

Я хочу подчеркнуть точку о том, о только первые несколько строк используется, и что при отладке и т.д. буфер, очевидно, все еще есть много данных, оставшихся в ней до отказа, так что ничего не бьет 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) {  

И вдруг все изменилось - а не ловить и сообщения об ошибке, процесс умирает через SIGABRT внутри try. Цепочка вызовов выглядит следующим образом:

#0 0x00007ffff6b2fa28 in __GI_raise ([email protected]=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 ([email protected]=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 (
    [email protected]=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:179 является try { data.getline(line, 1024) }.

Согласно этим несколько вопросов:

Похоже, на самом деле есть только две возможности здесь:

  1. Я где-то ушел и повредил экземпляр istringstream.

  2. В библиотеке есть ошибка.

С 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 был обновлен в системе.

+0

я держал пари, что это изменение ABI НКУ 5 проблем – strangeqargo

+0

может быть, некоторые линии длиннее, чем 1024? (тогда getline устанавливает failbit). Это может произойти в некоторых файлах/proc. Второй сбой внутри попытки может быть вызван ловлей через ссылку, а не константу ссылки. – Hcorg

+0

@strangeqargo Я думаю, что вы правы, см. Мой ответ (система работала на 8 дней и не перезагружалась после обновления libc). – delicateLatticeworkFever

ответ

2

Я считаю, что странное соображение, что это из-за совместимости с ABI, введенной в результате обновления libc, является правильным. Система была в течение 8 дней, и обновление произошло за это время.

После перезагрузки и без каких-либо изменений в коде, он компилируется и запускается без ошибок. Я тестировал и в другой системе, такой же результат.

Вероятно, мораль, если вы заметили, Glibc был обновлен, перезагрузите систему ...