【问题标题】:Segfault caused by std::ostream::sentry in this overload of stream operator流运算符重载中 std::ostream::sentry 导致的段错误
【发布时间】:2013-08-21 23:08:13
【问题描述】:

我的目标是重载 << 运算符,以便将 Param 类的对象正确打印到标准输出。

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 版本等不同)

问题:我的重载 &lt;&lt; 运算符的代码有什么问题?

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();
}

ma​​in.cpp

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

我的参数__lb

0.13
0.24
0.45

myparam__mid

0.29
0.39
0.56

myparam__ub

0.50
0.61
0.72

【问题讨论】:

    标签: c++ operator-overloading ostream


    【解决方案1】:

    函数ostream&amp; operator&lt;&lt; (ostream &amp;out, Param &amp;cParam) 需要一个return 语句。添加return out;后,一切正常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-03
      • 1970-01-01
      • 1970-01-01
      • 2013-03-25
      • 2013-10-10
      • 1970-01-01
      相关资源
      最近更新 更多