2013-08-20 2 views
0

Моя цель - перегрузить оператор <<, чтобы объекты класса Param были напечатаны соответствующим образом до стандартного.Segfault, вызванный std :: ostream :: sentry в этой перегрузке оператора потока

Класс Param определен в файлах globals.h и globals.cpp. Ниже этих файлов есть тестовая программа main.cpp. Далее ниже приведены 3 текстовых файла ввода myparam__lb, myparam__mid и myparam_ub. Поместите все эти файлы в один и тот же каталог, и это версия реального случая с уменьшенным размером.

Вот трассировку от реального случая:

#0 0x00007ffff772811e in std::ostream::sentry::sentry(std::ostream&)() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
#1 0x00007ffff7728829 in std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
#2 0x00007ffff7728c0f in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
#3 0x0000000000450d32 in initSimulation5() at ../simulation5.cpp:809 
#4 0x000000000042c853 in Policy::Policy (this=0x7fffffffb090) at ../globals_mode.cpp:183 
#5 0x00000000004325c4 in readPoliciesFromScript (policies=..., filename=...) at ../globals_utilities.cpp:321 
#6 0x0000000000436280 in main (argc=1, argv=0x7fffffffe0d8) at ../main.cpp:122 

Этот код работает правильно на другой машине, но на текущей машине, она возвращает ошибку сегментации. (Обе машины 64-бит Ubuntu, но разные ядра, версии Ubuntu и т. Д.)

ВОПРОС: Что не так с моим кодом для перегруженного оператора <<?

globals.h

//globals.h 
/* Initialize a Param object with the base file path to the 
* text files containing the low, mid, and high estimates. 
* If the low, mid, and high estimates are, respectively, 
* stored in files 
* 
* ./input/myparam__lb 
* ./input/myparam__mid 
* ./input/myparam__ub 
* 
* then the base file path should be "./input/myparam". 
*/ 
class Param { 
public: 
    Param(string baseFilePath, const int size); 

    /*! Set Param to its low estimates */ 
    void setLevelLow(); 

    /*! Set Param to its mid estimates */ 
    void setLevelMid(); 

    /*! Set Param to its high estimates */ 
    void setLevelHigh(); 

    /*! Display range of Param values using an ostream */ 
    friend ostream& operator<< (ostream &out, Param &cParam); 

    /* 
    * The overloaded operators below allow a Param object to be passed 
    * to a function as a (const|nonconst) std::vector<double>& and 
    * return a reference to the appropriate set of values based on 
    * whether the Param object is set to its low, mid, or high 
    * estimates. 
    */ 

    operator std::vector<double>&() { 
     if(level < 0) return lb; 
     if(level > 0) return ub; 
     return mid; 
    } 

    operator const std::vector<double>&() const { 
     if(level < 0) return lb; 
     if(level > 0) return ub; 
     return mid; 
    } 

private: 
    int level; 

    std::vector<double> lb; 
    std::vector<double> mid; 
    std::vector<double> ub; 

    void readRatesFromFile(std::vector<double>& x, const string filePath, const int size); 

}; 

globals.cpp

void Param::setLevelLow() { level = -1; } 

void Param::setLevelMid() { level = 0; } 

void Param::setLevelHigh() { level = 1; } 

ostream& operator<< (ostream &out, Param &cParam) { 

    /* obtain correct level of parameter */ 
    vector<double> *pParam; 
    switch(cParam.level) { 
    case -1: 
     pParam = &(cParam.lb); 
     out << "-"; 
     break; 
    case 0: 
     pParam = &(cParam.mid); 
     out << "0"; 
     break; 
    case 1: 
     pParam = &(cParam.ub); 
     out << "+"; 
     break; 
    default: 
     std::cerr << "level=" << cParam.level << " when calling <<(ostream&,Param&)"; 
      exit(1); 
      break; 
    } 

    /* obtain value(s) of parameter */ 
    streamsize pre = cout.precision(); 
    cout.precision(5); 
    out << " Value = "; 
    double smallest, largest; 
    smallest = *min_element(pParam->begin(), pParam->end()); 
    largest = *max_element(pParam->begin(), pParam->end()); 
    if(smallest==largest) { 
     out << smallest; 
    } else { 
     out << "[" << fixed << smallest << ", " << 
         fixed << largest << "]"; 
    } 
    cout.precision(pre); 
} 

Param::Param(string baseFilePath, const int size) { 

    /* Read lower-bound values from file */ 
    readRatesFromFile(lb, baseFilePath+"__lb", size); 

    /* Read midpoint estimate values from file */ 
    readRatesFromFile(mid, baseFilePath+"__mid", size); 

    /* Read upper-bound values from file */ 
    readRatesFromFile(ub, baseFilePath+"__ub", size); 

    /* by default use midpoint estimate */ 
    setLevelMid(); 
} 

void Param::readRatesFromFile(std::vector<double>& x, const string filePath, const int size) { 

    char line[100]; 

    x.clear(); 
    x.resize(size,0.0); 

    fstream f_in(filePath.c_str(), ios::in); 
    if(f_in.fail()) { 
     cerr << "ERROR: Param::param() failed to open file \"" << 
       filePath.c_str() << "\". Exiting...\n"; 
     exit(1); 
    } 
    for(int i=0; i<size; ++i) { 
     f_in.getline(line,100); 
     x[i]=strtod(line,NULL); 
    } 
    f_in.close(); 
} 

main.cpp

//main.cpp 
#include <iostream> 
#include "globals.h" 
int main(int argc, char** argv) { 
    Param d("./myparam",3); 
    std::cout << d << "\n"; 
    return 0; 
} 

myparam__lb

0.13 
0.24 
0.45 

myparam__mid

0.29 
0.39 
0.56 

myparam__ub

0.50 
0.61 
0.72 

ответ

2

Функция ostream& operator<< (ostream &out, Param &cParam) нуждается оператор возврата. После добавления return out; все хорошо.

Смежные вопросы