Segfault是由std::ostream::sentry在流运算符的过载中引起的

Segfault caused by std::ostream::sentry in this overload of stream operator

本文关键字:运算符 std 是由 ostream sentry Segfault      更新时间:2023-10-16

我的目标是重载<<运算符,以便将Param类的对象适当地打印为标准输出。

Param类在globals.hglobals.cpp文件中定义。在这些文件下面,有一个main.cpp测试程序。下面是3个文本输入文件myparam__lbmyparam__midmyparam_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

此代码在另一台机器上正确运行,但在当前机器上,它出现了segfault。(这两台机器都是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
函数ostream& operator<< (ostream &out, Param &cParam)需要一个return语句。添加return out;后,一切正常。
相关文章: