Странное поведение после добавления исключений - PullRequest
0 голосов
/ 22 марта 2019

Я добавил некоторую обработку исключений в некоторые функции моего проекта. До добавления обработки ошибок программа работала нормально. После добавления исключений я теперь получаю значения мусора в параметрах конструктора и мутатора, и я не уверен, откуда они берутся. Некоторые функции вызываются не из других мест, кроме конструктора, поэтому я понятия не имею, откуда они получают данные мусора.

Я также проверил утечки памяти с помощью valgrind и некоторую отладку с помощью gdb, но ничего не нашел. Я в своем уме. Я приложил образец конструктора cpp ниже и один из мутаторов с обработкой исключений.

Protofield.cpp

ProtoField::ProtoField(std::string t_name, std::string t_abbreviation, FieldType t_type, Base t_base, int t_mask, std::string t_description, int t_offset, int t_length){
    try{
        setName(t_name);
        setAbbreviation(t_abbreviation);
        setType(t_type);
        setBase(t_base);
        setMask(t_mask);
        setDescription(t_description);
        setOffset(t_offset);
        setLength(t_length);
        m_valueString = std::map<int, std::string>();
    }
    catch(std::runtime_error e){
        std::cerr<<"Error in ProtoField Constructor"<<std::endl;
        std::cerr<<e.what()<<std::endl;
        return;
    }
}
/*Removed for brevity*/
void ProtoField::setMask(int t_mask){
    if(mask != 0){
        std::stringstream ss;
        ss<<"Field " << m_abbreviation << " mask previously set: "<<m_mask;
        throw std::runtime_error(ss.str());
    }
    else{
        m_mask = t_mask;
    }
    return;
}
/*Removed for brevity*/

ProtoField.hpp

class ProtoField{
    private:
        std::string m_name;
        std::string m_abbreviation;
        FieldType m_type;
        Base m_base;
        int m_mask;
        std::string m_description;
        int m_offset;
        int m_length;
        std::map<int, std::string> m_valueString;
    public:
        ProtoField(
            std::string t_name = "",
            std::string t_abbreviation = "",
            FieldType t_type = FieldType::ft_invalid,
            Base t_base = Base::invalid,
            int t_mask = 0,
            std::string t_description = "", 
            int t_offset = -1,
            int t_length = -1
        );

        std::string getName();
        std::string getAbbreviation();
        FieldType getType();
        Base getBase();
        int getMask();
        std::string getDescription();
        int getOffset();
        int getLength();
        std::map<int, std::string> getValueString();

        void setName(std::string t_name);
        void setAbbreviation(std::string t_abbreviation);
        void setType(FieldType t_type);
        void setType(std::string t_typestr);
        void setBase(Base t_base);
        void setBase(std::string t_basestr);
        void setMask(int t_mask);
        void setDescription(std::string t_description);
        void setOffset(int t_offset);
        void setLength(int t_length);
        void addValueString(int t_key, std::string t_value);
        void removeValueString(int t_key);

        //other functions
        std::string to_string();
    };

Мне кажется, стоит упомянуть, что затрагиваются только целые числа. Другие значения, включая строки и перечисления, по-видимому, соответствуют их предыдущему поведению. Так что в показанном классе только маска, смещение и длина показывают странное поведение.

Редактировать: Для более подробной информации о том, где вызывается конструктор, я включил две известные мне функции.

void parser::parseFields(ProtoData& t_data, ptree::ptree t_subtree){
        try{
            std::vector<ProtoField> fields;
            for(auto val : t_subtree.get_child("")){
                ProtoField field;
                parseField(t_data, field, val.second);
                fields.push_back(field);
            }
            for(auto field:fields){
                t_data.addField(field);
            }
        }
        catch(ptree::ptree_bad_path error){
            std::cerr<<"Bad Path to Fields"<<std::endl;
        }
        catch(ptree::ptree_bad_data error){
            std::cerr<<"Bad Data to fields"<<std::endl;
        }
    }

    void parser::parseField(ProtoData& t_data, ProtoField& t_field, ptree::ptree t_subtree){
        try{
            t_field.setAbbreviation(t_subtree.get<std::string>("abbreviation"));
            t_field.setName(t_data.getName() + "_" + t_field.getAbbreviation());
            t_field.setBase(t_subtree.get<std::string>("base", "none"));
            t_field.setType(t_subtree.get<std::string>("type"));
        }
        catch(ptree::ptree_bad_path error){
            std::cerr<<"Bad Path to Field"<<std::endl;
        }
        catch(ptree::ptree_bad_data error){
            std::cerr<<"Bad Data to field"<<std::endl;
        }
    }

1 Ответ

0 голосов
/ 22 марта 2019

Ваш конструктор не инициализирует m_mask.Затем вы вызываете setMask, который читает это еще не инициализированное значение (предполагая, что строка if(mask != 0) должна быть if(m_mask != 0)).Это неопределенное поведение.Значение может быть любым.Когда это ненулевое значение, генерируется исключение.

Решение состоит в том, чтобы либо инициализировать m_mask перед вызовом setMask, либо присвоить m_mask непосредственно в конструкторе и не вызывать вспомогательную функцию,(А поскольку конструктор устанавливает маску, что можно сделать только один раз, почему эта функция вообще должна существовать?)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...